#!/bin/bash

print_help() {
	echo ""
	echo "Convert an archive from one format to another"
	echo ""
	echo "Usage:   to7zip [options] ...files"
	echo ""
	echo "Options:"
	echo "   -h, --help         Print this help text"
	echo "   -d, --delete-old   Delete converted file"
	echo "   -f, --force        Replace the file with the converted file even if the file exists"
	echo "   -r, --rezip        Extract and archive again even if the converted file is already a 7zip archive"
	echo "   -F, --format       The format of the output"
    echo "   -t, --thread       Set the number of threads for archive extraction and creation (default: $thread_count)"
	echo ""
}

short_args=hdfrF:t:
long_args=help,delete-old,force,rezip,format:,thread:

# default
rezip=
delete_old=
force=
zip_args=
thread_count=8
params=""

# Parse arguments
parsed_args=$(getopt --options $short_args --longoptions $long_args --name "$0" -- "$@")
if [[ $? -ne 0 ]]; then
	echo "Failed to parse arguments"
	exit 2
fi
eval set -- "$parsed_args"
while true; do
	case "$1" in
		-h|--help)
			print_help
	        exit 0
			;;
		-d|--delete-old)
            delete_old=y
			shift
			;;
		-f|--force)
            force=y
			shift
			;;
		-r|--rezip)
            rezip=y
			shift
			;;
		-F|--format)
            case "$2" in
                7z)
                    ;;
                zip)
                    zip_args="-tzip"
                    output_ext="zip"
                    ;;
                *)
                    echo "Unknown format: $2"
                    exit 1
            esac
			shift 2
			;;
		-t|--thread)
            thread_count="$2"
			shift 2
			;;
		--)
			shift
            break
            ;;
		*)
			break
            ;;
    esac
done

out_dir="$PWD"

if [[ -z "$zip_args" ]]; then
    zip_args="-t7z -m0=lzma2 -ms=on"
    output_ext=7z
fi

for f in "$@"; do
    tmp_dir="$(mktemp -d "$PWD/to7zip.XXX")"
    output="$(echo "$f" | sed -E 's/\.(7z|tar\.gz|zip|rar)$//g').$output_ext"
    backup_file="$output".backup
    do_backup=

    if [[ ! -r "$f" ]]; then
        echo "$f : No such file or directory"
        continue
    fi

    echo "$f -> $output"

    if [[ -f "$output" ]]; then
        if [[ -n "$force" ]] || [[ "$f" =~ .7z$ && -n "$rezip" ]]; then
            do_backup=y
        else
            echo "$output : file exists, refusing to continue (-f to force)"
            continue
        fi
    fi

    if [[ "$f" =~ \.tar[^/]*$ ]]; then
        if ! tar -xf "$f" -C "$tmp_dir" >/dev/null; then
            echo "$f : extract failed"
            continue
        fi
    elif [[ "$f" =~ \.tar|gz|bz2|zip|7z$ ]]; then
        if ! 7z e -mmt="$thread_count" -o"$tmp_dir" "$f" >/dev/null; then
            echo "$f : extract failed"
            continue
        fi
    elif [[ "$f" =~ \.rar$ ]]; then
        if ! unrar x "$f" "$tmp_dir" >/dev/null; then
            echo "$f : unrar failed"
            continue
        fi
    else
        cp -r "$f" "$tmp_dir"
    fi

    if [[ -n "$do_backup" ]]; then
        mv "$output" "$backup_file"
    fi

    pushd "$tmp_dir" >/dev/null
    7z a $zip_args -mx=9 -mmt="$thread_count" "$out_dir/$output" >/dev/null
    return_val=$?
    popd >/dev/null
    if [[ $return_val -eq 0  ]]; then
        if [[ -n "$do_backup" ]]; then
            rm -r "$backup_file"
        elif [[ -n "$delete_old" ]]; then
            rm -r "$f"
        fi
    else
        if [[ -n "$do_backup" ]]; then
            mv "$backup_file" "$output"
        fi
        echo "$f : 7z archive failed"
    fi

    rm -r "$tmp_dir"
done

