#!/bin/bash

# This script contains the common code for the autocommands.
MYID=$(id -u)
MYGRP=$(id -g)

_autocommandrun_volume() {
    local command="$1"
    local volume_name="$2"
    local backup_folder="$3"

    case "$command" in
        create)
            echo "Creating volume ${volume_name}"
            docker volume create ${volume_name}
            ;;
        nuke)
            echo "Nuking volume ${volume_name}"
            docker volume rm ${volume_name}
            ;;
        backup)
            echo "Backing up volume ${volume_name}"
            docker run --rm -v ${volume_name}:/volume -v ${backup_folder}:/backup debian bash -c "tar -czvf /backup/backup.tgz -C /volume . && chown -R $MYID:$MYGRP /backup"
            ;;
        restore)
            echo "Restoring volume ${volume_name}"
            docker volume rm ${volume_name}
            docker volume create ${volume_name}
            docker run --rm -v ${volume_name}:/volume -v ${backup_folder}:/backup debian bash -c "tar -xzvf /backup/backup.tgz -C /volume --strip-components=1"
            ;;
    esac
}   

_autocommandrun_path() {
    local command="$1"
    local path="$2"
    local backup_folder="$3"

    case "$command" in
        create)
            echo "Creating path ${path}"
            mkdir -p ${path}
            ;;
        nuke)
            echo "Nuking path ${path}"
            PATHPARENT=$(dirname ${path})
            PATHCHILD=$(basename ${path})
            if [ -d "${PATHPARENT}/${PATHCHILD}" ]; then
                docker run --rm -v ${PATHPARENT}:/volume debian bash -c "rm -rf /volume/${PATHCHILD}" || echo "Failed to nuke path ${path}"
            else
                echo "Path ${path} does not exist - nothing to nuke"
            fi
            ;;
        backup)
            echo "Backing up path ${path}"
            if [ -d "${path}" ]; then
                docker run --rm -v ${path}:/path -v ${backup_folder}:/backup debian bash -c "tar -czvf /backup/backup.tgz -C /path . && chown -R $MYID:$MYGRP /backup"
            else
                echo "Path ${path} does not exist - nothing to backup"
            fi
            ;;
        restore)
            echo "Restoring path ${path}"
            tar -xzvf ${backup_folder}/backup.tgz -C ${path} --strip-components=1
            ;;
    esac
}

_autocommandrun_file() {
    local command="$1"
    local filepath="$2"
    local backup_folder="$3"

    case "$command" in
        create)
            ;;
        nuke)
            rm -f ${filepath}
            ;;
        backup)
            echo "Backing up file ${filepath}"
            FILEPARENT=$(dirname ${filepath})
            FILENAME=$(basename ${filepath})
            if [ -f "${FILEPARENT}/${FILENAME}" ]; then
                docker run --rm-v ${FILEPARENT}:/volume -v ${backup_folder}:/backup debian bash -c "cp /volume/${FILENAME} /backup/${FILENAME} && chown -R $MYID:$MYGRP /backup"
            else
                echo "File ${filepath} does not exist - nothing to backup"
            fi
            ;;
        restore)
            echo "Restoring file ${filepath}"
            local FILENAME=$(basename ${filepath})
            cp ${backup_folder}/${FILENAME} ${filepath}
            ;;
    esac
}

_autocommandparse() {
    # first argument is the command
    # if the command is backup or restore, then the last two arguments are the backup file and the temporary path
    # all other arguments are of form:
    # key=value
    # where key can be one of volume, path or file.
    # value is the path or volume name.

    # we iterate over the key=value arguments, and for each we call:
    #    autorun <command> <backupfile> <key> <value>

    local command="$1"
    shift
    local backup_temp_path="$1"
    shift

    # Extract the backup file and temp path (last two arguments)
    local args=("$@")
    local arg_count=${#args[@]}
    
    # Process all key=value pairs
    for ((i=0; i<$arg_count; i++)); do
        local pair="${args[$i]}"
        
        # Skip if not in key=value format
        if [[ "$pair" != *"="* ]]; then
            continue
        fi
        
        local key="${pair%%=*}"
        local value="${pair#*=}"

        # create backup folder unique to key/value.
        local bfolder=$(echo "${key}_${value}" | tr -cd '[:alnum:]_-')
        local targetpath="${backup_temp_path}/${bfolder}"
        mkdir -p ${targetpath}

        # Key must be one of volume, path or file
        case "$key" in
            volume)
                _autocommandrun_volume "$command" "$value" "$targetpath"
                ;;
            path)
                _autocommandrun_path "$command" "$value" "$targetpath"
                ;;
            file)
                _autocommandrun_file "$command" "$value" "$targetpath"
                ;;
            *)
                _die "Unknown key $key passed to auto${command}. We only support volume, path and file."
                ;;
        esac
    done
}


autocreate() {
    _check_required_env_vars "TEMP_DIR"

    local create_temp_path="$TEMP_DIR/create"
    mkdir -p "$create_temp_path"
    _autocommandparse create "$create_temp_path" "$@"
    rm -rf "$create_temp_path"
}


autonuke() {
    _check_required_env_vars "TEMP_DIR"

    local nuke_temp_path="$TEMP_DIR/nuke"
    mkdir -p "$nuke_temp_path"
    _autocommandparse nuke "$nuke_temp_path" "$@"
    rm -rf "$nuke_temp_path"
}


autobackup() {
    _check_required_env_vars "BACKUP_FILE" "TEMP_DIR"
    local backup_temp_path="$TEMP_DIR/backup"

    mkdir -p "$backup_temp_path"
    echo "_autocommandparse [backup] [$backup_temp_path] [$@]"

    # backup the files into the temp path.
    _autocommandparse backup "$backup_temp_path" "$@"

    # create the backup file.
    tar zcvf "$BACKUP_FILE" -C "$backup_temp_path" .

    rm -rf "$backup_temp_path"
}


autorestore() {
    _check_required_env_vars "BACKUP_FILE" "TEMP_DIR"
    local backup_temp_path="$TEMP_DIR/restore"

    echo "_autocommandparse [restore] [$backup_temp_path] [$@]"

    mkdir -p "$backup_temp_path"

    # extract the backup file into the temp path.
    tar zxvf "$BACKUP_FILE" -C "$backup_temp_path" --strip-components=1

    # restore the files from the temp path.
    _autocommandparse restore "$backup_temp_path" "$@"

    rm -rf "$backup_temp_path"
}