#!/usr/bin/zsh

mode::enable() {
    local mode_path="${HOME}/.config/zsh/modes/$1.sh"
    [ ! -f "$mode_path" ] && echo "Mode not found!" && return 1
    export MODE__ACTIVE_MODE="$1"

    export MODE__OLD_PS1="$PS1"
    export PS1="($1) $PS1"

    # shellcheck disable=SC1090
    source "$mode_path"
}


mode::get_functions() {
    perl -ne '/^(?>function\s+)?([\x21-\x7e]+)\s*\(\)/ && print "$1\n"' < "$1"
}

mode::get_variables() {
    perl -ne '/^(?>declare\s+(?>--?\w+\s*)+\s*)?\s*([\x21-\x3c\x3e-\x7e]+)=.*$/ && print "$1\n"' < "$1"
}

mode::get_aliases() {
    perl -ne '/^(?:noglob\s+)?alias ([\x21-\x3c\x3e-\x7e]+)=/ && print "$1\n"' < "$1"
}

mode::disable() {
    export PS1="${MODE__OLD_PS1}"
    local mode_path="${HOME}/.config/zsh/modes/$MODE__ACTIVE_MODE.sh"

    unset -v "MODE__OLD_PS1"
    unset -v "MODE__ACTIVE_MODE"

    for mode_variable in $(mode::get_variables "$mode_path"); do
        unset "$mode_variable"
    done

    for mode_function in $(mode::get_functions "$mode_path"); do
        unset -f "$mode_function"
    done

    for mode_alias in $(mode::get_aliases "$mode_path"); do
        unalias "$mode_alias"
    done
}


mode::help() {
    echo "Usage:"
    echo "    mode <MODENAME>"
    echo
    echo "Available modes:"
    for mode in ~/.config/zsh/modes/*; do
        printf "    %s\n" "$(basename "${mode%.sh}")"
    done
}


m() {
    [ -n "$MODE__ACTIVE_MODE" ] && {
        mode::disable
        [ -z "$1" ] && return
    }

    [ -z "$1" ] && {
        echo 'Error: Missing mode name!'
        mode::help
        return 1
    } >&2

    case "$1" in
        "-h"|"--help")
            mode::help
            ;;
        *)
            mode::enable "$1" || mode::help >&2
            ;;
    esac
}

mm() {
    [ -z "$MODE__ACTIVE_MODE" ] && return 1

    local mode_path="${HOME}/.config/zsh/modes/$MODE__ACTIVE_MODE.sh"

    echo "Active mode: $MODE__ACTIVE_MODE"

    echo
    echo 'Aliases: '
    for mode_alias in $(mode::get_aliases "$mode_path"); do
        printf '    '
        alias "$mode_alias"
    done

    echo
    echo 'Functions:'
    for mode_function in $(mode::get_functions "$mode_path"); do
        echo "    $mode_function"
    done

    echo
    echo 'Variables:'
    for mode_variable in $(mode::get_variables "$mode_path"); do
        echo "    $mode_variable"
    done
}

alias 'm?'=mm
