' *
' * The project site is at: http://sourceforge.jp/projects/fishbornas/
' *
' * First author tiritomato 2012.
' *
' * Distributed under the FishbornArchiveShelf License (See
' *  file "Licenses/License.txt" contained in a project, or the following link.
' *  http://sourceforge.jp/projects/fishbornas/scm/svn/blobs/head/trunk/Licenses/License.txt)
' *
' * 2012.06.07 Initial Revision (tiritomato)
' *

Partial Public Class Logic
    Partial Public Class FileSystem

        Public Shared ReadOnly FormCheckSeparators() As Char = {IO.Path.DirectorySeparatorChar, IO.Path.AltDirectorySeparatorChar, IO.Path.VolumeSeparatorChar}
        Public Shared ReadOnly DirectorySeparators() As Char = {IO.Path.DirectorySeparatorChar, IO.Path.AltDirectorySeparatorChar}

        Private Shared ReadOnly ByteSizeString_strUnits() As String = {"Byte", "KByte", "MByte", "GByte"}
        Public Shared Function ByteSizeString(ByVal sz As Long) As String
            Dim fSize As Double = sz
            For idx As Integer = 0 To ByteSizeString_strUnits.Length - 2
                If fSize < 1024.0 Then Return Format(fSize, "#,##0.00") & " " & ByteSizeString_strUnits(idx)
                fSize = fSize / 1024.0
            Next
            Return Format(sz, "#,##0.00") & " " & ByteSizeString_strUnits(ByteSizeString_strUnits.Length - 1)
        End Function

        Public Shared Function DirectoryDelete(ByVal dir As Path) As Boolean
            If dir Is Nothing Then Return False
            Return DirectoryDelete(dir.ToString)
        End Function

        Public Shared Function DirectoryDelete(ByVal dir As String) As Boolean
            If IO.Directory.Exists(dir) = False Then Return False
            DirectoryDelete = True
            Try
                Dim di As New IO.DirectoryInfo(dir)
                If RemoveReadonlyAttribute(di) Then
                    di.Delete(True)
                Else
                    DirectoryDelete = False
                End If
            Catch ex As Exception
                DirectoryDelete = False
            End Try
        End Function

        Public Shared Function DirectoryExists(ByVal path As String) As Boolean
            Return IO.Directory.Exists(path)
        End Function

        Public Shared Function Exists(ByVal path As String) As Boolean
            Return DirectoryExists(path) OrElse FileExists(path)
        End Function

        Public Shared Sub FileDelete(ByVal path As Path)
            If path IsNot Nothing Then FileDelete(path.ToString)
        End Sub

        Public Shared Sub FileDelete(ByVal path As String)
            IO.File.Delete(path)
        End Sub

        Public Shared Function FileExists(ByVal path As String) As Boolean
            Return IO.File.Exists(path)
        End Function

        Public Shared Function GetPathExtention(ByVal s As String) As String
            Dim Name As String = GetPathName(s)
            If 0 < Name.IndexOf(".") Then
                For Each Code As Char In Name
                    If Code <> "."c And Char.IsWhiteSpace(Code) = False Then Return IO.Path.GetExtension(Name)
                Next
            End If
            Return String.Empty ' if "." only name, extention return empty string
        End Function

        Public Shared Function GetPathName(ByVal s As String) As String
            If String.IsNullOrWhiteSpace(s) Then Return String.Empty
            GetPathName = GetPathWithoutRoot(s)
            If String.IsNullOrWhiteSpace(GetPathName) Then
                GetPathName = String.Empty
            Else
                GetPathName = IO.Path.GetFileName(GetPathName)
            End If
        End Function

        Public Shared Function GetPathNameWithoutExtention(ByVal s As String) As String
            Dim Name As String = GetPathName(s)
            Dim Ext As String = GetPathExtention(Name)
            Return Name.Substring(0, Name.Length - Ext.Length)
        End Function

        Public Shared Function GetPathParent(ByVal s As String) As String
            GetPathParent = String.Empty
            Dim Path As String = Nothing, Root As String = SplitPathRoot(Path, s)
            If Not String.IsNullOrWhiteSpace(Path) Then
                GetPathParent = IO.Path.GetDirectoryName(Path)
                If String.IsNullOrWhiteSpace(GetPathParent) Then
                    GetPathParent = IO.Path.GetPathRoot(Path)
                End If
            End If
            If Root IsNot Nothing Then GetPathParent = Root & GetPathParent
        End Function

        Public Shared Function GetPathRoot(ByVal s As String) As String
            GetPathRoot = SplitPathRoot(Nothing, s)
        End Function

        Public Shared Function GetPathWithoutRoot(ByVal s As String) As String
            GetPathWithoutRoot = String.Empty
            SplitPathRoot(GetPathWithoutRoot, s)
        End Function

        Public Shared Function GetSystemIcon(ByVal ext As String) As Drawing.Bitmap
            Return SystemIconLoader.SingletonInstance()(ext)
        End Function

        Public Shared Function JoinPathElements(ByVal x As String, ByVal y As String) As String
            Return JoinPathElements(New String() {x, y})
        End Function

        Public Shared Function JoinPathElements(ByVal elements As System.Collections.Generic.IEnumerable(Of String)) As String
            Dim FirstSplitRoot As String = String.Empty, sb As New System.Collections.Generic.List(Of String)
            If elements IsNot Nothing Then
                Dim idx As Integer = 0
                For Each element As String In elements
                    Dim SplitPath As String = String.Empty, SplitRoot As String = SplitPathRoot(SplitPath, element)
                    If idx = 0 Then FirstSplitRoot = SplitRoot
                    If Not String.IsNullOrWhiteSpace(SplitPath) Then sb.Add(SplitPath)
                    idx += 1
                Next
            End If
            Return FirstSplitRoot & String.Join(IO.Path.DirectorySeparatorChar, sb)
        End Function

        Public Shared Function RemoveReadonlyAttribute(ByVal dirInfo As IO.DirectoryInfo) As Boolean

            RemoveReadonlyAttribute = True

            Try
                If (dirInfo.Attributes And IO.FileAttributes.ReadOnly) =
                    IO.FileAttributes.ReadOnly Then
                    dirInfo.Attributes = IO.FileAttributes.Normal
                End If

                Dim fi As IO.FileInfo
                For Each fi In dirInfo.GetFiles()
                    If (fi.Attributes And IO.FileAttributes.ReadOnly) = IO.FileAttributes.ReadOnly Then
                        fi.Attributes = IO.FileAttributes.Normal
                    End If
                Next fi

                Dim di As IO.DirectoryInfo
                For Each di In dirInfo.GetDirectories()
                    RemoveReadonlyAttribute(di)
                Next di

            Catch ex As Exception
                RemoveReadonlyAttribute = False
            End Try

        End Function

        Public Shared Function SplitPathRoot(ByRef GetPathWithoutRoot As String, ByVal Src As String) As String

            GetPathWithoutRoot = String.Empty

            Src = GetWhitespaceCheckedPath(Src)
            If String.IsNullOrWhiteSpace(Src) Then Return String.Empty

            Dim Match As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(Src, RegexPatterns.Root)
            If Match Is Nothing OrElse String.IsNullOrWhiteSpace(Match.Value) Then Return String.Empty

            If Not String.IsNullOrWhiteSpace(Match.Groups(3).Value) Then
                Dim PathWithoutRoot As String = GetDotCheckedPath(Match.Groups(3).Value)
                If String.IsNullOrWhiteSpace(PathWithoutRoot) = False Then
                    GetPathWithoutRoot = IO.Path.GetDirectoryName(PathWithoutRoot & IO.Path.DirectorySeparatorChar) ' remove last separator
                End If
            End If

            Return Match.Groups(1).Value & Match.Groups(2).Value

        End Function

        Private Shared Function GetWhitespaceCheckedPath(ByVal s As String) As String

            If String.IsNullOrWhiteSpace(s) Then Return String.Empty

            GetWhitespaceCheckedPath = s

            For Each SepCode As Char In FormCheckSeparators
                Dim SplitPath() As String = GetWhitespaceCheckedPath.Split(New Char() {SepCode})
                If SplitPath IsNot Nothing AndAlso 0 < SplitPath.Length Then
                    For idx As Integer = 0 To SplitPath.Length - 1
                        SplitPath(idx) = SplitPath(idx).Trim
                    Next
                    GetWhitespaceCheckedPath = String.Join(SepCode, SplitPath)
                End If
            Next

        End Function

        Private Shared Function GetDotCheckedPath(ByVal s As String) As String

            GetDotCheckedPath = String.Empty
            If String.IsNullOrWhiteSpace(s) Then Exit Function

            Dim SplitPath() As String = s.Split(DirectorySeparators)
            If SplitPath IsNot Nothing AndAlso 0 < SplitPath.Length Then

                For idx As Integer = 0 To SplitPath.Length - 1

                    SplitPath(idx) = SplitPath(idx).Trim

                    ' is whitespace or "." only element ?
                    Dim isCharFind As Boolean = False
                    For Each c As Char In SplitPath(idx)
                        isCharFind = Char.IsWhiteSpace(c) = False And c <> "."c
                        If isCharFind Then Exit For
                    Next
                    If isCharFind Then Continue For ' no, some char is find, do continue

                    ' SplitPath(idx) is whitespace or "." only element, Remove whitespace from SplitPath(idx)
                    Dim ReplaceIndex As Integer = 0
                    While ReplaceIndex < SplitPath(idx).Length
                        If Char.IsWhiteSpace(SplitPath(idx), ReplaceIndex) Then
                            SplitPath(idx) = SplitPath(idx).Remove(ReplaceIndex, 1)
                        Else
                            ReplaceIndex += 1
                        End If
                    End While

                Next

                GetDotCheckedPath = String.Join(DirectorySeparators(0), SplitPath)

            End If

        End Function

        Private Class RegexPatterns
            Public Shared ReadOnly Separators As String = IIf(0 < DirectorySeparators.Length, "\", String.Empty) & String.Join("\", DirectorySeparators)
            Public Shared ReadOnly Root As String = String.Format("^\s*(.*\{0})?([{1}]*)(.*)", IO.Path.VolumeSeparatorChar, Separators)
        End Class

    End Class
End Class

