Imports System.IO
Imports System.IO.Compression

Public Class zip
    Shared Sub ExtraeTodoDeZip(FicheroZIP As IO.MemoryStream, RutaDestino As String, Optional EliminaDirectorioDestino As Boolean = False)
        If RutaDestino.EndsWith("\") = False Then RutaDestino &= "\"
        If IO.Directory.Exists(RutaDestino) And EliminaDirectorioDestino Then
            IO.Directory.Delete(RutaDestino, True)
        End If
        If Not IO.Directory.Exists(RutaDestino) Then tsl5.Utilidades.CreaEstructuraDirectorio(RutaDestino)
        Dim fzip As New ZipArchive(FicheroZIP, ZipArchiveMode.Read)
        For Each entry In fzip.Entries
            Dim sDestino As String = RutaDestino & entry.FullName.Replace("/", "\")
            If Not IO.Directory.Exists(IO.Path.GetDirectoryName(sDestino)) Then
                tsl5.Utilidades.CreaEstructuraDirectorio(IO.Path.GetDirectoryName(sDestino))
            End If
            If entry.FullName.EndsWith("/") = False Then entry.ExtractToFile(sDestino)
        Next
    End Sub
    ''' <summary>
    ''' Esta función extrae el único fichero que hay dentro de un fichero zip, lo devuelve como array de bytes como retorno de la función, e indica su nombre en un parámetro por referencia.
    ''' </summary>
    ''' <param name="ficheroZip">Array de bytes conteniendo el fichero zip.</param>
    ''' <param name="nombreArchivoDentroZip">Cadena donde se guardará el nombre del fichero que está dentro del fichero zip.</param>
    ''' <returns>Para que este método funcione correctamente es imprescindible que el archivo zip tenga dentro un único fichero.</returns>
    Public Shared Function ExtraerFicheroUnicoDeZip(ficheroZip As Byte(), ByRef nombreArchivoDentroZip As String) As Byte()
        Dim sFichero As IO.Stream
        Dim za As ZipArchive = New ZipArchive(New IO.MemoryStream(ficheroZip))
        If za.Entries.Count = 1 Then
            nombreArchivoDentroZip = za.Entries.First.Name
            sFichero = za.Entries.First.Open()
        Else
            Throw New Exception("Se esperaba que el archivo zip tuviera un único fichero dentro, pero la cantidad es distinta. Se aborta la operación.")
        End If

        Dim ms As New IO.MemoryStream
        sFichero.CopyTo(ms)
        sFichero.Dispose()

        Return ms.ToArray
    End Function
    ''' <summary>
    ''' Esta función extrae todos los ficheros que haya en un zip y los devuelve como un diccionario.
    ''' </summary>
    ''' <param name="ficheroZip">Array de bytes conteniendo el fichero zip.</param>
    ''' <returns>Como todo es en memoria, hay que tener cuidado de que los ficheros extraídos quepan en memoria adecuadamente, teniendo en cuenta las posibles restricciones de memoria que el sistema operativo pueda tener para procesos individuales.</returns>
    Public Shared Function ExtraerFicherosDeZip(ficheroZip As Byte()) As Dictionary(Of String, IO.MemoryStream)
        Dim resultado As New Dictionary(Of String, IO.MemoryStream)
        Dim za As ZipArchive = New ZipArchive(New IO.MemoryStream(ficheroZip))
        For Each e In za.Entries
            resultado.Add(e.FullName, e.Open())
        Next
        Return resultado
    End Function




    Public Shared Function ComprimirArchivos(nombresFicheros As List(Of String), rutasFicheros As List(Of String), rutaZip As String) As Boolean
        Try
            ' Validar que ambas listas tengan el mismo número de elementos
            If nombresFicheros.Count <> rutasFicheros.Count Then
                Throw New ArgumentException("Las listas de nombres y rutas no tienen la misma longitud.")
            End If

            ' Crear el archivo ZIP
            Using zipStream As FileStream = New FileStream(rutaZip, FileMode.Create)
                Using zipArchive As ZipArchive = New ZipArchive(zipStream, ZipArchiveMode.Create)
                    For i As Integer = 0 To nombresFicheros.Count - 1
                        ' Agregar cada archivo al ZIP
                        Dim rutaArchivo As String = rutasFicheros(i)
                        Dim nombreEnZip As String = nombresFicheros(i)

                        If File.Exists(rutaArchivo) Then
                            zipArchive.CreateEntryFromFile(rutaArchivo, nombreEnZip)
                        Else
                            Console.WriteLine($"Advertencia: El archivo {rutaArchivo} no existe.")
                        End If
                    Next
                End Using
            End Using

            Console.WriteLine($"Archivo ZIP creado correctamente en: {rutaZip}")
            Return True
        Catch ex As Exception
            Console.WriteLine($"Error al crear el ZIP: {ex.Message}")
            Return False
        End Try
    End Function
    'prueba
End Class
