# Module:         poCompress
# Copyright:      Paul Obermeier 2000-2025 / paul@poSoft.de
# First Version:  2025 / 09 / 06
#
# Distributed under BSD license.
#
# Module with compressing functionality.

namespace eval poCompress {
    variable ns [namespace current]

    namespace ensemble create

    namespace export Pack Unpack
    namespace export List

    proc Pack { compressedFile level args } {
        if { ! [poMisc HavePkg "tar"] } {
            error "Pack: Package \"tar\" not available."
        }
        set catchVal [catch {open $compressedFile wb} fp]
        if { $catchVal != 0 } {
            error "Could not open file \"$compressedFile\" for writing."
        }
        if { $level < 1 } {
            ::tar::create $fp $args -chan
        } else {
            ::zlib push gzip $fp -level $level
            ::tar::create $fp $args -chan
        }
        close $fp
    }

    proc Unpack { compressedFile dir } {
        if { ! [poMisc HavePkg "tar"] } {
            error "Unpack: Package \"tar\" not available."
        }
        set catchVal [catch {open $compressedFile rb} fp]
        if { $catchVal != 0 } {
            error "Could not open file \"$compressedFile\" for reading."
        }
        ::tar::untar $fp -dir $dir -chan
        close $fp
    }

    proc List { compressedFile } {
        set zipList [list]
        if { [poType IsCompressed $compressedFile "zip"] } {
            if { ! [poMisc HavePkg "fileutil::decode"] } {
                error "List: Package \"fileutil::decode\" not available."
            }
            if { ! [poMisc HavePkg "zipfile::decode"] } {
                error "List: Package \"zipfile::decode\" not available."
            }

            ::zipfile::decode::open $compressedFile
            set zipDict [::zipfile::decode::archive]
            foreach name [::zipfile::decode::files $zipDict] {
                if { [string index $name end] ne "/" } {
                    set size [::zipfile::decode::filesize $zipDict $name]
                    set date [::zipfile::decode::filetime $zipDict $name]
                    set fileAttr [list "name" $name "size" $size "date" $date]
                    lappend zipList $fileAttr
                }
            }
            ::zipfile::decode::close
        } elseif { [poType IsCompressed $compressedFile "tar"] || \
                   [poType IsCompressed $compressedFile "gzip"] } {
            if { ! [poMisc HavePkg "tar"] } {
                error "List: Package \"tar\" not available."
            }
            set catchVal [catch {open $compressedFile rb} fp]
            if { $catchVal != 0 } {
                error "Could not open file \"$compressedFile\" for reading."
            }
            set fileCont [::tar::stat $fp "" -chan]
            close $fp
            foreach { name info } $fileCont {
                if { [dict get $info type] ne "directory" } {
                    set size [dict get $info size]
                    set date [clock format [dict get $info mtime] -format "%Y-%m-%d %H:%M:%S"]
                    set fileAttr [list "name" $name "size" $size "date" $date]
                    lappend zipList $fileAttr
                }
            }
        }
        return $zipList
    }
}
