#!/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}"
            local path_parent=$(dirname ${path})
            local path_child=$(basename ${path})
            if [ -d "${path_parent}/${path_child}" ]; then
                docker run --rm -v ${path_parent}:/volume debian bash -c "rm -rf /volume/${path_child}" || 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}"
            local file_parent=$(dirname ${filepath})
            local file_name=$(basename ${filepath})
            if [ -f "${file_parent}/${file_name}" ]; then
                docker run --rm -v ${file_parent}:/volume -v ${backup_folder}:/backup debian bash -c "cp /volume/${file_name} /backup/${file_name} && chown -R $MYID:$MYGRP /backup"
            else
                echo "File ${filepath} does not exist - nothing to backup"
            fi
            ;;
        restore)
            echo "Restoring file ${filepath}"
            local file_name=$(basename ${filepath})
            cp ${backup_folder}/${file_name} ${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

    echo "autocommandparse: command=$command backup_temp_path=$backup_temp_path"

    # 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
}


datacreate() {
    _autocommandparse create none "$@"
}


datanuke() {
    _autocommandparse nuke none "$@"
}

databackup() {
    _check_required_env_vars "BACKUP_FILE" "TEMP_DIR"
    BACKUP_TEMP_PATH="$TEMP_DIR/backup"


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

    tar zcvf "$BACKUP_FILE" -C "$BACKUP_TEMP_PATH" .
}

datarestore() {
    _check_required_env_vars "BACKUP_FILE" "TEMP_DIR"
    BACKUP_TEMP_PATH="$TEMP_DIR/restore"

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

    mkdir -p "$BACKUP_TEMP_PATH"
    tar zxvf "$BACKUP_FILE" -C "$BACKUP_TEMP_PATH" --strip-components=1

    _autocommandparse restore "$BACKUP_TEMP_PATH" "$@"
}