Imports System.Collections.Concurrent
Imports System.IO
Imports System.Collections.Generic
Imports MaddoShared

Public Class FileHelper
    'Private dirSourceDest As Dictionary(Of FileInfo, DirectoryInfo)
    Private filesPerFolder As Integer
    Private suffix As String
    Private counterSize As Integer
    Private numerationType As Integer
    Private filter As String
    Private separateFiles As Boolean
    Private extensions As String = "*.jpg,*.png,*.gif"


    Public Enum numerazione
        Progressiva
        Files
    End Enum
    ''' <summary>
    ''' Preparazione per la separazione
    ''' </summary>
    ''' <param name="filesPerFolder"></param>
    ''' <param name="suffix"></param>
    ''' <param name="counterSize"></param>
    ''' <param name="numerationType"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal filesPerFolder As Integer, ByVal suffix As String, ByVal counterSize As Integer, ByVal numerationType As Integer)
        Me.filesPerFolder = filesPerFolder
        Me.suffix = suffix
        Me.counterSize = counterSize
        Me.numerationType = numerationType
        Me.separateFiles = True
    End Sub

    ''' <summary>
    ''' nessuna separazione
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        Me.separateFiles = False
    End Sub


    Public Function GetFilesRecursive(ByVal root As DirectoryInfo, ByVal destRoot As DirectoryInfo, ByVal filter As String) As Dictionary(Of FileInfo, DirectoryInfo)
        Dim dirSourceDest As New Dictionary(Of FileInfo, DirectoryInfo)
        Dim result As New List(Of FileInfo)

        'Dim stack As New Stack(Of DirectoryInfo)
        Dim stack As New Stack(Of KeyValuePair(Of DirectoryInfo, DirectoryInfo))


        Me.filter = filter
        Dim pair As New KeyValuePair(Of DirectoryInfo, DirectoryInfo)


        'stack.Push(root)
        stack.Push(New KeyValuePair(Of DirectoryInfo, DirectoryInfo)(root, destRoot))

        Do While (stack.Count > 0)
            Dim curDirKV As KeyValuePair(Of DirectoryInfo, DirectoryInfo) = stack.Pop
            'curDirKP = stack.Pop()
            Dim dir As DirectoryInfo = curDirKV.Key
            Dim dDir As DirectoryInfo = curDirKV.Value
            Try
                'result.AddRange(dir.GetFiles(filter, SearchOption.TopDirectoryOnly))
                ' dividere file qui
                If filesPerFolder > 0 And separateFiles Then
                    appendDictionary(dirSourceDest, dividiFilesInDir(dir, dDir))
                Else
                    appendDictionary(dirSourceDest, getAllFilesInDir(dir, dDir))
                End If



                For Each subDirectory As DirectoryInfo In dir.GetDirectories
                    stack.Push(New KeyValuePair(Of DirectoryInfo, DirectoryInfo)(subDirectory, New DirectoryInfo(Path.Combine(dDir.FullName, subDirectory.Name))))

                Next
            Catch ex As Exception
                Dim e As Exception = ex.Demystify()
                Console.WriteLine(e)
                Console.WriteLine(e.Message)
                Console.WriteLine(e.StackTrace)
            End Try
        Loop

        Return dirSourceDest
    End Function

    'Public Class FileData
    '    Public File As FileInfo
    '    Public Directory As DirectoryInfo
    '    Public Sub New(newFile As FileInfo, newDirectory As DirectoryInfo)
    '        File = newFile
    '        Directory = newDirectory
    '    End Sub
    'End Class

    'Public Function GetFilesRecursiveParallel(ByVal root As DirectoryInfo, ByVal destRoot As DirectoryInfo, ByVal filter As String) As List(Of FileData)


    '    Dim dirSourceDest As New ConcurrentDictionary(Of FileInfo, DirectoryInfo)
    '    Dim result As New List(Of FileInfo)

    '    'Dim stack As New Stack(Of DirectoryInfo)
    '    Dim stack As New Stack(Of KeyValuePair(Of DirectoryInfo, DirectoryInfo))


    '    Me.filter = filter
    '    Dim pair As New KeyValuePair(Of DirectoryInfo, DirectoryInfo)


    '    'stack.Push(root)
    '    stack.Push(New KeyValuePair(Of DirectoryInfo, DirectoryInfo)(root, destRoot))

    '    Do While (stack.Count > 0)
    '        Dim curDirKV As KeyValuePair(Of DirectoryInfo, DirectoryInfo) = stack.Pop
    '        'curDirKP = stack.Pop()
    '        Dim dir As DirectoryInfo = curDirKV.Key
    '        Dim dDir As DirectoryInfo = curDirKV.Value
    '        Try
    '            'result.AddRange(dir.GetFiles(filter, SearchOption.TopDirectoryOnly))
    '            ' dividere file qui
    '            If filesPerFolder > 0 And separateFiles Then
    '                AppendDictionaryConcurrent(dirSourceDest, DividiFilesInDirConcurrent(dir, dDir))
    '            Else
    '                AppendDictionaryConcurrent(dirSourceDest, DividiFilesInDirConcurrent(dir, dDir))
    '            End If

    '            For Each subDirectory As DirectoryInfo In dir.GetDirectories
    '                stack.Push(New KeyValuePair(Of DirectoryInfo, DirectoryInfo)(subDirectory, New DirectoryInfo(Path.Combine(dDir.FullName, subDirectory.Name))))

    '            Next
    '        Catch ex As Exception
    '            ' TODO: FARE QUALCOSA
    '        End Try
    '    Loop

    '    Dim resultData As New List(Of FileData)
    '    resultData.AddRange(From p In dirSourceDest Select New FileData(p.Key, p.Value))
    '    Return resultData
    '    'Return dirSourceDest
    'End Function

    Public Function appendDictionary(ByVal dictA As Dictionary(Of FileInfo, DirectoryInfo), ByVal dictB As Dictionary(Of FileInfo, DirectoryInfo)) As Dictionary(Of FileInfo, DirectoryInfo)
        For Each pair As KeyValuePair(Of FileInfo, DirectoryInfo) In dictB
            dictA.Add(pair.Key, pair.Value)
        Next
        Return dictA
    End Function

    'Public Function AppendDictionaryConcurrent(ByVal dictA As ConcurrentDictionary(Of FileInfo, DirectoryInfo), ByVal dictB As ConcurrentDictionary(Of FileInfo, DirectoryInfo)) As ConcurrentDictionary(Of FileInfo, DirectoryInfo)
    '    For Each pair As KeyValuePair(Of FileInfo, DirectoryInfo) In dictB
    '        dictA.TryAdd(pair.Key, pair.Value)
    '        'dictA.Add(pair.Key, pair.Value)
    '    Next
    '    Return dictA
    'End Function

    Public Function getAllFilesInDir(dir As DirectoryInfo, dirDest As DirectoryInfo) As Dictionary(Of FileInfo, DirectoryInfo)
        Dim dict As New Dictionary(Of FileInfo, DirectoryInfo)
        For Each File As FileInfo In dir.GetFiles(filter)
            dict.Add(File, New DirectoryInfo(Path.Combine(dirDest.FullName, File.Name)))

        Next
        Return dict
    End Function

    Private Function dividiFilesInDir(dir As DirectoryInfo, dirDest As DirectoryInfo) As Dictionary(Of FileInfo, DirectoryInfo)
        Dim filesCount As Integer = dir.GetFiles(filter).Count
        Dim contaFilePerDir As Integer = 0
        Dim contaDirPerDir As Integer = 0
        Dim tempText As String = String.Empty
        Dim foldersDict As New Dictionary(Of FileInfo, DirectoryInfo)

        Dim destDir As DirectoryInfo
        destDir = New DirectoryInfo(Path.Combine(dirDest.FullName))
        For Each file As FileInfo In dir.GetFiles(filter)

            contaFilePerDir += 1

            If contaFilePerDir = (contaDirPerDir * filesPerFolder) + 1 Then
                contaDirPerDir += 1

                If numerationType = numerazione.Progressiva Then
                    tempText = contaDirPerDir.ToString
                Else
                    tempText = (contaDirPerDir * filesPerFolder).ToString
                End If
                Dim i As Integer
                For i = 1 To (counterSize - tempText.Length)
                    tempText = "0" & tempText
                Next
                destDir = New DirectoryInfo(Path.Combine(dirDest.FullName, suffix + tempText))



            End If

            If Not destDir.Exists Then
                destDir.Create()
            End If

            foldersDict.Add(file, destDir)
        Next

        Return foldersDict
    End Function

    Private Function DividiFilesInDirConcurrent(dir As DirectoryInfo, dirDest As DirectoryInfo) As ConcurrentDictionary(Of FileInfo, DirectoryInfo)
        Dim filesCount As Integer = dir.GetFiles(filter).Count
        Dim contaFilePerDir As Integer = 0
        Dim contaDirPerDir As Integer = 0
        Dim tempText As String = String.Empty
        Dim foldersDict As New ConcurrentDictionary(Of FileInfo, DirectoryInfo)

        Dim destDir As DirectoryInfo
        destDir = New DirectoryInfo(Path.Combine(dirDest.FullName))
        For Each file As FileInfo In dir.GetFiles(filter)

            contaFilePerDir += 1

            If contaFilePerDir = (contaDirPerDir * filesPerFolder) + 1 Then
                contaDirPerDir += 1

                If numerationType = numerazione.Progressiva Then
                    tempText = contaDirPerDir.ToString
                Else
                    tempText = (contaDirPerDir * filesPerFolder).ToString
                End If
                Dim i As Integer
                For i = 1 To (counterSize - tempText.Length)
                    tempText = "0" & tempText
                Next
                destDir = New DirectoryInfo(Path.Combine(dirDest.FullName, suffix + tempText))



            End If

            If Not destDir.Exists Then
                destDir.Create()
            End If

            foldersDict.TryAdd(file, destDir)
        Next

        Return foldersDict
    End Function
End Class
