#!/bin/bash

show_help() {
    echo "usage: fs-state mock-dir [dirname]"
    echo "       fs-state restore-dir [dirname]"
    echo "       fs-state mock-file [filename]"
    echo "       fs-state restore-file [filename]"
    echo "       fs-state start-monitor"
    echo "       fs-state check-monitor"
}

_mock_dir() {
    local dir="$1"
    if [ ! -d "$dir" ]; then
        echo "fs-state: created mock directory: $dir"
        mkdir -p "$dir"
        touch "$dir.fake"
    fi
}

mock_dir() {
    local dir="$1"

    if [ -d "$dir" ]; then
        mv "$dir" "$dir.back"
    fi
    _mock_dir "$dir"
}

restore_dir() {
    local dir="$1"

    if [ -e "$dir.fake" ]; then
        echo "fs-state: restoring mocked directory: $dir"
        rm -rf "$dir"
        rm -f "$dir.fake"
    else
        echo "fs-state: cannot restore non-mocked directory: $dir" >&2
        exit 1
    fi
    if [ -d "$dir.back" ]; then
        mv "$dir.back" "$dir"
    fi
}

_mock_file() {
    local file="$1"
    if [ ! -e "$file" ]; then
        echo "fs-state: creating file: $file"
        echo "The file is a mock file used by fs-state." > "$file"
        echo "The .fake file is a marker file used by fs-state." > "$file.fake"
    fi
}

mock_file() {
    local file="$1"

    if [ -e "$file" ]; then
        echo "fs-state: backing up original file: $file"
        mv "$file" "$file.back"
    fi
    # ensure the parent dir is available
    if [ ! -d "$(dirname "$file")" ]; then
        mkdir -p "$(dirname "$file")"
    fi
    _mock_file "$file"
}

restore_file() {
    local file="$1"
    if [ -e "$file.fake" ]; then
        echo "fs-state: restoring mocked file: $file"
        rm -f "$file"
        rm -f "$file.fake"
    else
        echo "fs-state: cannot restore non-mocked file: $file" >&2
        exit 1
    fi
    if [ -e "$file.back" ]; then
        mv "$file.back" "$file"
    fi
}

save_current_tree(){
    local dir=$1

    rm -rf "$dir"
    mkdir "$dir"
    # .snap files created in tests/lib/snaps are excluded as they are not deleted to be reused
    # runtime-state dir contains cursor and run log which are created during the first test
    find /etc ! -name "*~" > "$dir"/etc
    find /boot ! -name "*~" > "$dir"/boot
    find /home ! -name "*~" | grep -v -e "$PROJECT_PATH/tests/lib/snaps/.*/.*.snap" -e "$PWD/.*.snap" > "$dir"/home
    find /root ! -name "*~" > "$dir"/root
}

start_monitor() {
    if os.query is-classic; then
        save_current_tree /tmp/fs-initial
    fi
 }

skip_monitor() {
    local path=$1
    echo "$path" >> /tmp/fs-skip
}

clean_skipped() {
    # shellcheck disable=SC2002
    cat /tmp/fs-skip | while read -r file; do
        for filename in /tmp/fs-initial/*; do
            sed -i "/$file/d" "$filename"
        done
        for filename in /tmp/fs-final/*; do
            sed -i "/$file/d" "$filename"
        done
    done
}

check_monitor() {
    save_current_tree /tmp/fs-final
    clean_skipped

    rm -f /tmp/fs-diff
    for f in /tmp/fs-initial/*; do
        diff /tmp/fs-initial/"$f" /tmp/fs-final/"$f" >> /tmp/fs-diff
    done

    if [ ! -e /tmp/fs-diff ]; then
        echo "the /tmp/fs-diff file does not exist"
        exit 1
    fi
    if [ -n "$(cat /tmp/fs-diff)" ]; then
        echo "the diff file is not empty:"
        cat /tmp/fs-diff 
        exit 1
    fi
}

main() {
    if [ $# -eq 0 ]; then
        show_help
        exit 0
    fi

    action=
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help|'')
                show_help
                exit 0
                ;;
            *)
                action=$(echo "$1" | tr '-' '_')
                shift
                break
                ;;
        esac
    done

    "$action" "$@"
}

main "$@"
