' *
' * 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 AppBase
    Partial Public Class Archive

        Public Class ZipProcess
            Inherits ArchiveProcess.Impl(Of ZipOptionConfig)

            Public Sub New(ByVal src As ZipOptionConfig, ByVal AppBase As AppBase, Optional ByVal IsStopReq As Logic.Threading.SignalHandler = Nothing)
                MyBase.New(src, AppBase, IsStopReq)
            End Sub

            Public Overrides Function CrcCheck(ByVal Path As Logic.FileSystem.Path) As RESULT

                If Path.FileExists = False Then Return RESULT.NO_FILE
                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT

                CrcCheck = RESULT.OK

                Dim hZip As Ionic.Zip.ZipFile = Nothing
                Dim hBuf As New IO.MemoryStream
                Try
                    Dim opt As New Ionic.Zip.ReadOptions
                    opt.Encoding = System.Text.Encoding.GetEncoding(0)
                    hZip = Ionic.Zip.ZipFile.Read(Path.ToString, opt)
                    If 0 < hZip.Count Then
                        hZip.ExtractExistingFile = Ionic.Zip.ExtractExistingFileAction.OverwriteSilently
                        For idx As Integer = 0 To hZip.Count - 1
                            hBuf = New IO.MemoryStream
                            If AppBase IsNot Nothing Then AppBase.Echoing.Log.Echo(hZip(idx).FileName, AppendLogArgs.LogType.ConsoleOut)
                            hZip(idx).Extract(hBuf)
                            hBuf.Close()
                            hBuf = Nothing
                            If AppBase IsNot Nothing Then AppBase.Echoing.Progress.Echo(idx, hZip.Count)
                            If IsStopRequested() Then
                                CrcCheck = RESULT.USER_CANCEL
                                Exit For
                            End If
                        Next
                    End If
                Catch ex As Ionic.Zip.BadCrcException
                    CrcCheck = RESULT.ARCHIVE_CRC_ERR
                Catch ex As Ionic.Zip.BadPasswordException
                    CrcCheck = RESULT.ARCHIVE_PASSWORD_MISSMATCH
                Catch ex As Exception
#If DEBUG Then
                    Throw
#End If
                    CrcCheck = RESULT.ARCHIVE_EXTRACT_ERR
                Finally
                    If Not hBuf Is Nothing Then hBuf.Close()
                    If Not hZip Is Nothing Then hZip.Dispose()
                End Try

            End Function

            Public Overrides Function Extract(ByVal DestDir As Logic.FileSystem.Path, ByVal SrcArcPath As Logic.FileSystem.Path) As RESULT

                If SrcArcPath.FileExists = False Then Return RESULT.NO_FILE
                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT

                Extract = RESULT.OK

                Dim hZip As Ionic.Zip.ZipFile = Nothing
                Try
                    hZip = New Ionic.Zip.ZipFile(SrcArcPath.ToString, System.Text.Encoding.GetEncoding(0))
                    AddHandler hZip.ExtractProgress, AddressOf ExtractProgressEcho
                    hZip.ExtractAll(DestDir.ToString, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently)
                Catch ex As Ionic.Zip.BadCrcException
                    Extract = RESULT.ARCHIVE_CRC_ERR
                Catch ex As Ionic.Zip.BadPasswordException
                    Extract = RESULT.ARCHIVE_PASSWORD_MISSMATCH
                Catch ex As Exception
#If DEBUG Then
                    Throw
#End If
                    Extract = RESULT.ARCHIVE_EXTRACT_ERR
                Finally
                    If Not hZip Is Nothing Then hZip.Dispose()
                End Try

            End Function

            Public Overrides Function Extract(ByRef DestBuf As IO.MemoryStream, ByVal SrcEntryPath As String, ByVal SrcArcPath As Logic.FileSystem.Path) As RESULT

                DestBuf = Nothing

                If SrcArcPath.FileExists = False Then Return RESULT.NO_FILE
                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT

                Extract = RESULT.OK

                Dim hZip As Ionic.Zip.ZipFile = Nothing
                Try
                    Dim opt As New Ionic.Zip.ReadOptions
                    opt.Encoding = System.Text.Encoding.GetEncoding(0)
                    hZip = Ionic.Zip.ZipFile.Read(SrcArcPath.ToString, opt)
                    Dim entry As Ionic.Zip.ZipEntry = hZip(SrcEntryPath)
                    If Not entry Is Nothing Then
                        DestBuf = New IO.MemoryStream
                        entry.Extract(DestBuf)
                    End If
                Catch ex As Ionic.Zip.BadCrcException
                    Extract = RESULT.ARCHIVE_CRC_ERR
                Catch ex As Ionic.Zip.BadPasswordException
                    Extract = RESULT.ARCHIVE_PASSWORD_MISSMATCH
                Catch ex As Exception
#If DEBUG Then
                    Throw
#End If
                    Extract = RESULT.ARCHIVE_EXTRACT_ERR
                Finally
                    If Not hZip Is Nothing Then hZip.Dispose()
                    If Extract <> RESULT.OK AndAlso (Not DestBuf Is Nothing) Then
                        DestBuf.Close()
                        DestBuf = Nothing
                    End If
                End Try

            End Function

            Public Overrides Function CompressDir(ByVal DestArcPath As Logic.FileSystem.Path, ByVal SrcDir As Logic.FileSystem.Path) As RESULT

                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT
                Dim Path As New CompressPathInfo(DestArcPath.ToString, SrcDir.ToString, BaseConfig.Extention)
                If Path.Exists = False Then Return RESULT.NO_DIRECTORY

                CompressDir = RESULT.OK

                Dim strSelectionStore As String = BaseConfig.SelectionStore

                Try
                    Dim hZip As New Ionic.Zip.ZipFile(System.Text.Encoding.GetEncoding(0))
                    hZip.CompressionLevel = BaseConfig.nLv
                    hZip.AddSelectedFiles(BaseConfig.SelectionCompress, SrcDir.ToString, "", True)
                    If Not String.IsNullOrWhiteSpace(strSelectionStore) Then
                        hZip.CompressionLevel = ZipCompressionLv.None
                        hZip.AddSelectedFiles(strSelectionStore, SrcDir.ToString, "", True)
                    End If
                    CompressDirProgressCount = New CompressDirProgressCounter(hZip.Count)
                    AddHandler hZip.SaveProgress, AddressOf CompressDirProgressEcho
                    hZip.Save(DestArcPath.ToString)
                Catch ex As Exception
                    If AppBase IsNot Nothing Then AppBase.Echoing.Log.Echo(ex.Message)
                    CompressDir = RESULT.ARCHIVE_COMPRESS_ERR
#If DEBUG Then
                    Throw
#End If
                End Try

                If IsStopRequested() Then CompressDir = RESULT.USER_CANCEL

            End Function

            Public Overrides Function GetEntryList(ByRef Dest() As String, ByVal SrcArcPath As Logic.FileSystem.Path) As RESULT

                Dest = Nothing
                If SrcArcPath.FileExists = False Then Return RESULT.NO_FILE
                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT

                GetEntryList = RESULT.OK
                Dim hZip As Ionic.Zip.ZipFile = Nothing
                Try
                    Dim opt As New Ionic.Zip.ReadOptions
                    opt.Encoding = System.Text.Encoding.GetEncoding(0)
                    hZip = Ionic.Zip.ZipFile.Read(SrcArcPath.ToString, opt)
                    If 0 < hZip.Count Then
                        ReDim Dest(hZip.Count - 1)
                        For idx As Integer = 0 To hZip.Count - 1
                            Dest(idx) = hZip(idx).FileName
                        Next
                    End If
                Catch ex As Ionic.Zip.BadCrcException
                    GetEntryList = RESULT.ARCHIVE_CRC_ERR
                Catch ex As Ionic.Zip.BadPasswordException
                    GetEntryList = RESULT.ARCHIVE_PASSWORD_MISSMATCH
                Catch ex As Exception
#If DEBUG Then
                    Throw
#End If
                    GetEntryList = RESULT.ARCHIVE_EXTRACT_ERR
                Finally
                    If GetEntryList <> RESULT.OK AndAlso (Not Dest Is Nothing) Then Dest = Nothing
                    If Not hZip Is Nothing Then hZip.Dispose()
                End Try

            End Function

            Public Overrides Function GetEntryList(ByRef Dest() As EntryInfo, ByVal SrcArcPath As Logic.FileSystem.Path) As RESULT

                Dest = Nothing
                If SrcArcPath.FileExists = False Then Return RESULT.NO_FILE
                If BaseConfig Is Nothing Then Return RESULT.NO_OBJECT

                GetEntryList = RESULT.OK
                Dim hZip As Ionic.Zip.ZipFile = Nothing
                Try
                    Dim opt As New Ionic.Zip.ReadOptions
                    opt.Encoding = System.Text.Encoding.GetEncoding(0)
                    hZip = Ionic.Zip.ZipFile.Read(SrcArcPath.ToString, opt)
                    If 0 < hZip.Count Then
                        ReDim Dest(hZip.Count - 1)
                        For idx As Integer = 0 To hZip.Count - 1
                            Dim tmp As EntryInfo
                            tmp.EntryPath = hZip(idx).FileName
                            If Not hZip(idx).IsDirectory Then
                                tmp.CompressedSize = hZip(idx).CompressedSize
                                tmp.ExtractSize = hZip(idx).UncompressedSize
                                If 0 < tmp.ExtractSize Then tmp.CompressionRatio = hZip(idx).CompressedSize / hZip(idx).UncompressedSize
                                Dim TryCrc As UInt32
                                If UInt32.TryParse(hZip(idx).Crc.ToString("X"), System.Globalization.NumberStyles.HexNumber, Nothing, TryCrc) Then
                                    tmp.Crc32 = TryCrc
                                End If
                                tmp.ModifiedTime = hZip(idx).LastModified
                            End If
                            Dest(idx) = tmp
                        Next
                    End If
                Catch ex As Ionic.Zip.BadCrcException
                    GetEntryList = RESULT.ARCHIVE_CRC_ERR
                Catch ex As Ionic.Zip.BadPasswordException
                    GetEntryList = RESULT.ARCHIVE_PASSWORD_MISSMATCH
                Catch ex As Exception
#If DEBUG Then
                    Throw
#End If
                    GetEntryList = RESULT.ARCHIVE_EXTRACT_ERR
                Finally
                    If GetEntryList <> RESULT.OK AndAlso (Not Dest Is Nothing) Then Dest = Nothing
                    If Not hZip Is Nothing Then hZip.Dispose()
                End Try

            End Function

            Private Class CompressDirProgressCounter
                Public ReadOnly Max As Integer
                Private _Val As Integer
                Public Sub New(ByVal nMax As Integer)
                    Max = nMax
                    _Val = 0
                End Sub
                Public ReadOnly Property Val As Integer
                    Get
                        Val = _Val
                    End Get
                End Property
                Public Function Increment() As Integer
                    SyncLock Me
                        _Val += 1
                        Increment = _Val
                    End SyncLock
                End Function
            End Class
            Private CompressDirProgressCount As CompressDirProgressCounter

            Private Sub DefaultConsoleEcho(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs)
                If Not String.IsNullOrEmpty(outLine.Data) And AppBase IsNot Nothing Then AppBase.Echoing.Log.Echo(outLine.Data, AppendLogArgs.LogType.ConsoleOut)
            End Sub

            Private Sub ExtractProgressEcho(ByVal sender As Object, ByVal e As Ionic.Zip.ExtractProgressEventArgs)
                If AppBase IsNot Nothing Then
                    Select Case e.EventType
                        Case Ionic.Zip.ZipProgressEventType.Extracting_BeforeExtractEntry
                            AppBase.Echoing.Log.Echo(e.CurrentEntry.FileName, AppendLogArgs.LogType.ConsoleOut)
                        Case Ionic.Zip.ZipProgressEventType.Extracting_AfterExtractEntry
                            AppBase.Echoing.Progress.Echo(e.EntriesExtracted, e.EntriesTotal)
                    End Select
                End If
            End Sub

            Private Sub CompressDirProgressEcho(ByVal sender As Object, ByVal e As Ionic.Zip.SaveProgressEventArgs)
                Select Case e.EventType
                    Case Ionic.Zip.ZipProgressEventType.Saving_AfterWriteEntry
                        If Not String.IsNullOrEmpty(e.CurrentEntry.FileName) Then
                            If IsStopRequested() Then
                                e.Cancel = True
                            Else
                                CompressDirProgressCount.Increment()
                            End If
                            If e.Cancel = False Then
                                AppBase.Echoing.Log.Echo(e.CurrentEntry.FileName, AppendLogArgs.LogType.ConsoleOut)
                                AppBase.Echoing.Progress.Echo(Fix(CDbl(CompressDirProgressCount.Val) / CDbl(CompressDirProgressCount.Max) * 100.0), 100)
                            End If
                        End If
                End Select
            End Sub

        End Class

    End Class
End Class


