#!/bin/bash

# 显示帮助信息
show_help() {
    echo "Usage: $0 [-f | --extract] | [-d | --compress] | [-h | --extract-here]"
    echo "  -f, --extract          解压文件并提示进度"
    echo "  -d, --compress         压缩文件并选择格式"
    echo "  -h, --extract-here     解压到文件所在目录"
    echo "  --help                 显示帮助信息"
}
remove_suffix() {
    local filename="$1"
    # 常见压缩后缀名列表
    local suffixes=(
        ".tar.gz" ".tar.bz2" ".tar.xz"
        ".gz" ".bz2" ".xz" ".zip" ".rar" ".7z"
    )
    
    # 检查是否匹配常见压缩后缀
    for suffix in "${suffixes[@]}"; do
        if [[ "$filename" == *"$suffix" ]]; then
            echo "${filename%"$suffix"}"
            return
        fi
    done
    
    # 如果没有匹配，去掉最后一个点之后的内容
    echo "${filename%.*}"
}

# 判断是否安装了必要的工具
check_tools() {
    if ! command -v zenity &> /dev/null; then
        echo "Error: zenity is not installed."
        exit 1
    fi
    if ! command -v 7z &> /dev/null; then
        echo "Error: 7z is not installed."
        exit 1
    fi
}

function run_with_progress(){
    # 启动传入的命令并在后台运行
    "$@" &

    # 获取上一个命令的进程ID（PID）
    pid=$!
    until ! kill -0 $pid 2>/dev/null; do
    # 循环输出 1 到 99，直到命令执行完成
    for i in {1..99}; do
        if ! kill -0 $pid 2>/dev/null; then
            break
        fi
        echo $i
        sleep 0.1  # 可以调整输出速度，避免过于频繁
    done
    done
    # 等待命令结束


}

function check_exist(){
for arg in "$@";do
if [[ ! -e "$arg" ]];then
garma --error --text="文件或目录不存在\nFile or Directory does not exist."

exit 1
fi
done
}
function ask_if_overwrite(){
if [[ -e "$1" ]];then
    if garma --question --text="$1 已被占用，是否覆盖？\n$1 is occulied. Overwrite?";then
        true
    else
        
        exit 1
    fi
fi
}

function create_tar(){
    ask_if_overwrite "$FILE_NO_SUFFIX.tar"
    tar -cvf "$FILE_NO_SUFFIX.tar" --files-from=/dev/null
    for FILE_TO_ADD in "$@"; do
        # 进入目标文件夹
        pushd "$(dirname "${FILE_TO_ADD}")" 
        # 使用完整路径且引用文件名以避免特殊字符的问题
        tar -rvf "$FILE_NO_SUFFIX.tar" --no-wildcards "./$(basename "${FILE_TO_ADD}")"
        # 返回原目录
        popd 
    done
}

# 压缩功能
compress_files() {
# 合并选择压缩格式与是否设置密码的选项
FORMAT=$(zenity --height=500 --width=500 --list --radiolist --column="Choose" --column="Format" TRUE "zip"  FALSE "7z"  FALSE "tar" FALSE "tar.xz" FALSE "tar.bz2" FALSE "tar.gz" FALSE "7z (加密Encrypt)" FALSE "zip (加密Encrypt)" --title="选择压缩格式 Choose Compress Format")
if [ -z "$FORMAT" ]; then
    echo "取消压缩操作"
    exit 1
fi

# 判断用户是否选择加密选项
ENCRYPT=false
if [[ "$FORMAT" == "7z (加密Encrypt)" || "$FORMAT" == "zip (加密Encrypt)" ]]; then
    ENCRYPT=true
    FORMAT="${FORMAT%% (加密Encrypt)}"  # 移除加密选项文字，只保留格式
fi

# 选择文件保存路径
FILE=$(zenity --file-selection --save --filename="$(dirname "$1")/$(remove_suffix $(basename "$1")).${FORMAT}" --title="选择保存压缩文件的路径 Choose archive file path" --file-filter="$FORMAT files (*.$(echo "$FORMAT" | tr '[:upper:]' '[:lower:]'))|*.$(echo "$FORMAT" | tr '[:upper:]' '[:lower:]')")
if [ -z "$FILE" ]; then
    echo "取消压缩操作"
    exit 1
fi

# 如果选择加密，提示用户输入密码
if [ "$ENCRYPT" = true ]; then
    PASSWORD=$(zenity --password --title="输入压缩密码 Enter Archive Password")
    if [ -z "$PASSWORD" ]; then
        zenity --error --text="未设置密码，取消操作。\nNo password set, operation cancelled."
        exit 1
    fi
fi
    # 根据选择的格式执行压缩操作
    FILE_NO_SUFFIX="$(remove_suffix ${FILE})"
    (case "$FORMAT" in
        "7z")

            if [ -n "$PASSWORD" ]; then
                ask_if_overwrite "$FILE"
                tmp_file=$(mktemp -d)
                7z a -t7z  "$FILE" "$@" -p"$PASSWORD" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


            else
                ask_if_overwrite "$FILE"
                tmp_file=$(mktemp -d)
                7z a -t7z "$FILE" "$@" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


            fi 

            ;;
        "zip")
            if [ -n "$PASSWORD" ]; then
                ask_if_overwrite "$FILE"
                7z a -tzip  "$FILE" "$@" -p"$PASSWORD"  -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


            else
                ask_if_overwrite "$FILE"
                7z a -tzip  "$FILE" "$@" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


            fi 
        ;;
        "tar")
            run_with_progress create_tar "$@"
            ;;
        "tar.xz")
            echo "5"
            create_tar "$@"
            run_with_progress xz -T0 -v "$FILE_NO_SUFFIX.tar"
            ;;
        "tar.bz2")
            echo "5"
            create_tar "$@"
            run_with_progress bzip2 -v "$FILE_NO_SUFFIX.tar"
            ;;
        "tar.gz")
            echo "5"
            create_tar "$@"
            run_with_progress pigz "$FILE_NO_SUFFIX.tar"
            ;;
        *)
            echo "不支持的格式"
            
            exit 1
            ;;
    esac
    ) | garma --progress  --auto-close --auto-kill --text="正在执行操作 Processing..."

    garma --info --text="压缩完成！Finished" 
}

# 通用解压逻辑函数
extract_single_file() {
    local FILE="$1"
    local EXTRACT_DIR="$2"


    while true; do
        case "$FILE" in
            *.7z)
                if ! 7z t "$FILE" -p$(uuid); then
                    PASSWORD=$(zenity --entry --title="密码保护 Password Required" --text="文件 $FILE 受密码保护，请输入密码\nFile $FILE is password protected. Please enter the password.")
                    [ -z "$PASSWORD" ] && echo "取消解压操作"  && break

                    if ! 7z t "$FILE" -p"$PASSWORD"; then                    
                    zenity --error --title="密码错误 Wrong Password" --text="密码错误，请重试\nIncorrect password, please try again."
                    else
                    yes | 7z x  -p"$PASSWORD" "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


                    break
                    fi
                else
                    yes | 7z x  "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"

                    break
                fi  
                ;;
            *.zip)
                if ! 7z t "$FILE" -p$(uuid); then
                    PASSWORD=$(zenity --entry --title="密码保护 Password Required" --text="文件 $FILE 受密码保护，请输入密码\nFile $FILE is password protected. Please enter the password.")
                    [ -z "$PASSWORD" ] && echo "取消解压操作"  && break
                    if ! 7z t "$FILE" -p"$PASSWORD"; then                    
                    zenity --error --title="密码错误 Wrong Password" --text="密码错误，请重试\nIncorrect password, please try again."
                    else
                    output=$(zipu "$FILE" 2>&1)
                    if echo "$output" | grep -q "All file names are properly in UTF8 encoding" || echo "$output" | grep -q "Detected encoding  :  ascii"; then
                        yes | 7z x  -p"$PASSWORD" "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


                    else
                        run_with_progress zipu --extract --password="$PASSWORD" "$FILE" "$EXTRACT_DIR" 
                     if [[ "$?" != "0" ]];then
                        zenity --warning --text="此文件不使用UTF8编码且自动修复失败，将会使用7z解压，编码可能有问题\nThis file is not using UTF8 coding and we failed to fix it. Will use 7z to extract, while the coding might be incorrect" --timeout=5 
                        yes | 7z x  -p"$PASSWORD" "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


                     fi
                    fi
                    break
                    fi
                    
                else
                    output=$(zipu "$FILE" 2>&1)
                    if echo "$output" | grep -q "All file names are properly in UTF8 encoding" || echo "$output" | grep -q "Detected encoding  :  ascii"; then
                        yes | 7z x  "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"


                    else
                        run_with_progress zipu --extract "$FILE" "$EXTRACT_DIR" 
                     if [[ "$?" != "0" ]];then
                        zenity --warning --text="此文件不使用UTF8编码且自动修复失败，将会使用7z解压，编码可能有问题\nThis file is not using UTF8 coding and we failed to fix it. Will use 7z to extract, while the coding might be incorrect" --timeout=5 
                        yes | 7z x  "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"

                     fi
                    fi
                    break
                fi
                ;;
            *.rar)
                if ! 7z t "$FILE" -p$(uuid); then
                    PASSWORD=$(zenity --entry --title="密码保护 Password Required" --text="文件 $FILE 受密码保护，请输入密码\nFile $FILE is password protected. Please enter the password.")
                    [ -z "$PASSWORD" ] && echo "取消解压操作" && break
                    yes | 7z x  -p"$PASSWORD" "$FILE" -o"$EXTRACT_DIR" && break || \
                    zenity --error --title="密码错误 Wrong Password" --text="密码错误，请重试\nIncorrect password, please try again."
                else
                     yes | 7z x  "$FILE" -o"$EXTRACT_DIR" -bsp1 -bb1 -bse2 | grep --line-buffered -oP "(\d+(\.\d+)?(?=%))"

                    break
                fi
                ;;
            *.tar | *.tar.xz | *.tar.bz2 | *.tar.gz)
                run_with_progress tar -xvf "$FILE" -C "$EXTRACT_DIR"
                break
                ;;
            *.deb)
            DEBPATH="$FILE"
            ABS_DEBPATH="$(realpath "$DEBPATH")"
            OUTPATH="$EXTRACT_DIR"
            ABS_OUTPATH="$(realpath "$OUTPATH")"
            package_name=$(dpkg-deb -f "$DEBPATH" Package)
            mkdir -p "$OUTPATH/$package_name/DEBIAN/"
            dpkg -e "$DEBPATH" "$OUTPATH/$package_name/DEBIAN/"
            run_with_progress dpkg -X "$DEBPATH" "$OUTPATH/$package_name/"
            break
            ;;
            *)
                run_with_progress tar -xvf "$FILE" -C "$EXTRACT_DIR"
                break
                ;;
        esac
    done
}

# 解压到指定目录
extract_files() {
    local EXTRACT_DIR
    EXTRACT_DIR=$(zenity --file-selection --directory --title="选择解压到的文件夹 Choose extract to dir")
    [ -z "$EXTRACT_DIR" ] && echo "取消解压操作"  && exit 1

    (for FILE in "$@"; do
        local TARGET_DIR="$EXTRACT_DIR/$(remove_suffix $(basename "$FILE"))"
        echo "$FILE $(basename "$FILE") $(remove_suffix $(basename "$FILE"))"
        ask_if_overwrite "$TARGET_DIR"
        mkdir -p "$TARGET_DIR"
        extract_single_file "$FILE" "$TARGET_DIR"
    done
    )| garma --progress  --auto-close --auto-kill --text="正在执行操作 Processing..."
        if [[ -e  "${EXTRACT_DIR}" ]];then
            xdg-open "${EXTRACT_DIR}"
        fi
}

# 解压到当前目录
extract_here() {
        (for FILE in "$@"; do
        local EXTRACT_DIR
        EXTRACT_DIR=$(dirname "$FILE")
        local TARGET_DIR="$EXTRACT_DIR/$(remove_suffix $(basename "$FILE"))"
        ask_if_overwrite "$TARGET_DIR"
        mkdir -p "$TARGET_DIR"
        extract_single_file "$FILE" "$TARGET_DIR"
        if [[ "$#" -lt "2" ]];then
            xdg-open ${TARGET_DIR}
        fi
    done
    )| garma --progress  --auto-close --auto-kill --text="正在执行操作 Processing..."
        if [[ "$#"  -gt "1" ]];then
        garma --info --text="解压完成！Finished" 
        fi
        
}


# 主逻辑
check_tools

case "$1" in
    -f|--extract)
        shift
    if [[ -z "$@" ]];then
    FILE=$(zenity --file-selection --title="选择要解压的文件 Choose file to extract" --file-filter="*.7z *.zip *.rar *.tar *.tar.xz *.tar.bz2 *.tar.gz")
    if [ -z "$FILE" ]; then
        echo "取消解压操作"
        
        exit 1
    fi
    check_exist "$FILE"
    extract_files "$FILE"
    else
    check_exist "$@"
    extract_files "$@"
    fi
        ;;
    -d|--compress)
        shift 
        if [[ -z "$@" ]];then
    FILE=$(zenity --file-selection --directory --title="选择要压缩的目录 Choose dir to compress")
    if [ -z "$FILE" ]; then
        echo "取消压缩操作"
        
        exit 1
    fi
        check_exist "${FILE}"
    compress_files "${FILE}"
    else
        check_exist "$@"
        compress_files "$@"
    fi
        ;;
    -h|--extract-here)
        shift 
    # 获取当前文件的路径并解压到所在目录
    if [[ -z "$@" ]];then
    FILE=$(zenity --file-selection --title="选择要解压的文件 Choose file to uncompress" --file-filter="*.7z *.zip *.rar *.tar *.tar.xz *.tar.bz2 *.tar.gz")
    if [ -z "$FILE" ]; then
        echo "取消解压操作"
        
        exit 1
    fi
        check_exist "$FILE"
    extract_here "$FILE"
    else
    check_exist "$@"
    extract_here "$@"
    fi
        ;;
    --help)
        show_help
        ;;
    *)
        declare -a COMPRESSION_TOOLS=("deepin-compressor" "ark" "engrampa" "file-roller")
        # Function to check if a command exists
        command_exists() {
            command -v "$1" &>/dev/null
        }

            for tool in "${COMPRESSION_TOOLS[@]}"; do
                if command_exists "$tool"; then
                    "$tool" "$@"
                    exit
                fi
            done
        zenity --error --text="未能找到支持的压缩工具，无法启动图形界面。请使用 $0 --help 来查看命令行用法\nNo supported compression tool found! Can not initiate graphic intersurface. Use $0 --help to check cli usage"
        exit 1

        ;;

esac
