#!/usr/bin/env bash

# TODO: in the readme, remind the user that they don't have to write a fully
# fledged config if they only want to modify a single element (like "normal
# delta"), if the other values are not specified, the default values will be
# used

## Default controller values
DEFAULT_VOLUME_CONTROLLER="pamixer"
DEFAULT_INCREASE_FLAG="--increase"
DEFAULT_DECREASE_FLAG="--decrease"
DEFAULT_SET_VOLUME_FLAG="--set-volume"
DEFAULT_SET_MUTE_FLAG="--mute"
DEFAULT_SET_UNMUTE_FLAG="--unmute"
DEFAULT_TOGGLE_MUTE_FLAG="--toggle-mute"
DEFAULT_GET_VOLUME_FLAG="--get-volume"
DEFAULT_GET_MUTE_FLAG="--get-mute"
DEFAULT_ADDITIONAL_FLAGS=("--allow-boost")

## Default values
DEFAULT_NOTIFICATION_ENABLED=1
DEFAULT_NOTIFICATION_TIMEOUT=3000

DEFAULT_NORMAL_DELTA=5
DEFAULT_BIG_DELTA=10


VERBOSE=0

CONFIG_PATH="${XDG_CONFIG_HOME:-$HOME/.config}/volumectl/config.ini"
READ_INI_POSSIBLE_PATHS=(\
    "${XDG_LIB_HOME:-$HOME/.local/lib}/read_ini.sh"  "${XDG_LIB_HOME:-$HOME/.local/lib}/bash_ini_parser/read_ini.sh" \
)


## Args
OPTIONAL_FLAGS=( \
    "-v" "--verbose" \
    "-c" "--config" \
    "-h" "-?" "--help" \
)

verbose () {
    [[ $VERBOSE -eq 1 ]] && return 0 || return 1
}

notify () {
    volume=$(get_volume)
    muted=$(get_mute)

    if [[ $muted = "true" ]]; then
        icon="audio-volume-muted"
    elif [[ $volume -eq 0 ]]; then
        icon="audio-volume-low"
    elif [[ $volume -gt 0 ]] && [[ $volume -lt 50 ]]; then 
        icon="audio-volume-medium"
    elif [[ $volume -ge 50 ]]; then 
        icon="audio-volume-high"
    fi

    local cmd="dunstify -h int:value:$volume -t $NOTIFICATION_TIMEOUT -h string:x-dunst-stack-tag:volume -i \"$icon\" \"Volume ($volume%)\""
    [[ $NOTIFICATION_ENABLED -eq 1 ]] && sh -c "$cmd"
    # verbose && ( [[ $NOTIFICATION_ENABLED -eq 1 ]] && echo "Notified with \`$cmd\`" || echo "Didn't notify" )
}


get_parser_location () {
    local parser_location=""
    for location in "${READ_INI_POSSIBLE_PATHS[@]}"; do
        [[ -f "$location" ]] && parser_location="$location" && break
    done

    echo "$parser_location"
}

checkout_config () {
    local parser_location="$(get_parser_location)"

    if [[ ! -z "$parser_location" ]]; then
        verbose && echo "Sourcing the ini parser"
        source "$parser_location"
        if [[ -f "$CONFIG_PATH" ]]; then
            verbose && echo "Reading the config file '$CONFIG_PATH'"
            read_ini "$CONFIG_PATH"
        else
            verbose && echo "Unable to find the config file '$CONFIG_PATH', using default script values"
        fi
    else
        verbose && echo "Unable to find the 'read_ini.sh' file, which is used to read the config file. Will be using the default vlaues of the script." 
    fi

    VOLUME_CONTROLLER=${INI__Controller__volume_controller:-$DEFAULT_VOLUME_CONTROLLER}
    INCREASE_FLAG=${INI__Controller__increase_flag:-$DEFAULT_INCREASE_FLAG}
    DECREASE_FLAG=${INI__Controller__decrease_flag:-$DEFAULT_DECREASE_FLAG}
    SET_VOLUME_FLAG=${INI__Controller__set_volume_flag:-$DEFAULT_SET_VOLUME_FLAG}
    SET_MUTE_FLAG=${INI__Controller__set_mute_flag:-$DEFAULT_SET_MUTE_FLAG}
    SET_UNMUTE_FLAG=${INI__Controller__set_unmute_flag:-$DEFAULT_SET_UNMUTE_FLAG}
    TOGGLE_MUTE_FLAG=${INI__Controller__toggle_mute_flag:-$DEFAULT_TOGGLE_MUTE_FLAG}
    GET_VOLUME_FLAG=${INI__Controller__get_volume_flag:-$DEFAULT_GET_VOLUME_FLAG}
    GET_MUTE_FLAG=${INI__Controller__get_mute_flag:-$DEFAULT_GET_MUTE_FLAG}
    ADDITIONAL_FLAGS=${INI__Controller__additional_flags:-$DEFAULT_ADDITIONAL_FLAGS}

    NORMAL_DELTA=${INI__Controller__normal_delta:-$DEFAULT_NORMAL_DELTA}
    BIG_DELTA=${INI__Controller__big_delta:-$DEFAULT_BIG_DELTA}
    
    NOTIFICATION_ENABLED=${INI__Notification__enabled:-$DEFAULT_NOTIFICATION_ENABLED}
    NOTIFICATION_TIMEOUT=${INI__Notification__timeout:-$DEFAULT_NOTIFICATION_TIMEOUT}


    verbose && echo "" && echo "After parsing the config file, variables are:" && \
        echo "VOLUME_CONTROLLER: '$VOLUME_CONTROLLER'" && \
        echo "INCREASE_FLAG: '$INCREASE_FLAG'" && \
        echo "DECREASE_FLAG: '$DECREASE_FLAG'" && \
        echo "SET_VOLUME_FLAG: '$SET_VOLUME_FLAG'" && \
        echo "GET_VOLUME_FLAG: '$GET_VOLUME_FLAG'" && \
        echo "SET_MUTE_FLAG: '$SET_MUTE_FLAG'" && \
        echo "GET_MUTE_FLAG: '$GET_MUTE_FLAG'" && \
        echo "ADDITIONAL_FLAGS: '${ADDITIONAL_FLAGS[@]}'" && \
        echo "NORMAL_DELTA: '$NORMAL_DELTA'" && \
        echo "BIG_DELTA: '$BIG_DELTA'" && \
        echo "NOTIFICATION_ENABLED: '$NOTIFICATION_ENABLED'" && \
        echo "NOTIFICATION_TIMEOUT: '$NOTIFICATION_TIMEOUT'" && \
        echo ""
    
}

volume_up_by () {
    local cmd="$VOLUME_CONTROLLER ${ADDITIONAL_FLAGS[@]} $INCREASE_FLAG $1"
    verbose && echo "Increasing volume by $1, with \`$cmd\`"

    verbose && echo "Volume before command: $(get_volume)"
    sh -c "$cmd"
    verbose && echo "Volume after command: $(get_volume)"
    notify
}

volume_down_by () {
    local cmd="$VOLUME_CONTROLLER ${ADDITIONAL_FLAGS[@]} $DECREASE_FLAG $1"
    verbose && echo "Decreasing volume by $1, with \`$cmd\`"
    
    verbose && echo "Volume before command: $(get_volume)"
    sh -c "$cmd"
    verbose && echo "Volume after command: $(get_volume)"
    notify
}

volume_set () {
    local cmd="$VOLUME_CONTROLLER ${ADDITIONAL_FLAGS[@]} $SET_VOLUME_FLAG $1"
    verbose && echo "Setting the volume to $1, with \`$cmd\`"
   
    verbose && echo "Volume before command: $(get_volume)"
    sh -c "$cmd"
    verbose && echo "Volume after command: $(get_volume)"
    notify
}

volume_big_up () {
    local cmd="volume_up_by $BIG_DELTA"
    verbose && echo "Increasing the volume alot, with \`$cmd\`"
    $cmd
}

volume_big_down () {
    local cmd="volume_down_by $BIG_DELTA"
    verbose && echo "Decreasing the volume alot, with \`$cmd\`"
    $cmd
}

volume_up () {
    local cmd="volume_up_by $NORMAL_DELTA"
    verbose && echo "Increasing the volume, with \`$cmd\`"
    $cmd
}

volume_down () {
    local cmd="volume_down_by $NORMAL_DELTA"
    verbose && echo "Decreasing the volume, with \`$cmd\`"
    $cmd
}

toggle_mute() {
    local cmd="$VOLUME_CONTROLLER $TOGGLE_MUTE_FLAG"
    verbose && echo "Toggling the mute, with \`$cmd\`"

    verbose && echo "Mute state before command: $(get_mute)"
    sh -c "$cmd"
    verbose && echo "Mute state after command: $(get_mute)"
    notify
}


mute () {
    local cmd="$VOLUME_CONTROLLER $SET_MUTE_FLAG"
    verbose && echo "Setting the mute on, with \`$cmd\`"
   
    verbose && echo "Mute state before command: $(get_mute)"
    sh -c "$cmd"
    verbose && echo "Mute state after command: $(get_mute)"
    notify
}

unmute () {
    local cmd="$VOLUME_CONTROLLER $SET_UNMUTE_FLAG"
    verbose && echo "Setting the mute off, with \`$cmd\`"
    
    verbose && echo "Mute state before command: $(get_mute)"
    sh -c "$cmd"
    verbose && echo "Mute state after command: $(get_mute)"
    notify
}

get_volume () {
    sh -c "$VOLUME_CONTROLLER ${ADDITIONAL_FLAGS[@]} $GET_VOLUME_FLAG"
}

get_mute () {
    sh -c "$VOLUME_CONTROLLER ${ADDITIONAL_FLAGS[@]} $GET_MUTE_FLAG"
}

usage() {
    cat << EOF
volumectl - A configurable bash script that makes your life easier in controlling volume and notifying it
at the same time.

Usage:  volumectl [-v|--verbose] [-c|--config path] -option [arg]      

Options:
    -i [arg], --increase [arg]          increase the volume by the "normal" amount or by the [arg] amount
    -d [arg], --decrease [arg]          decrease the volume by the "normal" amount or by the [arg] amount
    -I, --big-increase                  increase the volume by the "big" amount
    -D, --big-decrease                  decrease the volume by the "big" amount
    -s arg, --set arg                   set volume to arg
    -m, --mute                          mute
    -u, --unmute                        unmute
    -t, --toggle                        toggle mute
    -g, --get-volume                    get volume
    -G, --get-mute                      get mute

Optional arguments:
    -c path, --config path              instead of reading from the default location ($CONFIG_PATH),
                                        read from the path given
    -v, --verbose                       print each step the script passes through
    -h, -?, --help                      show this message
EOF
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then #if '__name__' == '__main__'

    while [[ " ${OPTIONAL_FLAGS[@]} " =~ " $1 " ]]; do
        verbose && echo "Checking for optional arguments"
        case $1 in 
            -v|--verbose)
                VERBOSE=1
                echo "Setting \$VERBOSE to 1 (\$VERBOSE=$VERBOSE)"
                shift
                ;;
            -c|--config)
                [[ -f "$2" ]] && CONFIG_PATH="$2" || echo "Error: the config file given '$2' doesn't exists." 1>&2 && exit 1
                verbose && echo "Setting \$CONFIG_PATH to $2 (\$CONFIG_PATH=$CONFIG_PATH)"
                shift 2
                ;;
            -h|-\?|--help)
                verbose && echo "Detected -h, -? or --help"
                usage
                exit
                ;;
        esac
    done

    checkout_config
    
    verbose && echo "Looking at the argument '$@'"
    case $1 in 
        -i|--increase) 
            verbose && echo "Detected -i or --increase, with argument '$2'"
            [[ -z "$2" ]] && volume_up || volume_up_by $2
            ;;
        -I|--big-increase) 
            verbose && echo "Detected -I or --big-increase"
            volume_big_up
            ;;
        -d|--decrease) 
            verbose && echo "Detected -d or --decrease, with argument '$2'"
            [[ -z "$2" ]] && volume_down || volume_down_by $2
            ;;
        -D|--big-decrease) 
            verbose && echo "Detected -D or --big-decrease"
            volume_big_down
            ;;
        -s|--set-volume)
            verbose && echo "Detected -s or --set-volume, with argument '$2'"
            [[ -z "$2" ]] && echo "Error, missing value to set volume" 1>&2 && exit 1 || volume_set $2
            ;;
        -m|--set-mute) 
            verbose && echo "Detected -m or --mute"
            mute
            ;;
        -u|--ummute) 
            verbose && echo "Detected -u or --unmute"
            unmute
            ;;
        -t|--toggle-mute) 
            verbose && echo "Detected -t or --toggle-mute"
            toggle_mute
            ;;
        -g|--get-volume) 
            verbose && echo "Detected -g or --get-volume"
            get_volume
            ;;
        -G|--get-mute) 
            verbose && echo "Detected -G or --get-mute"
            get_mute
            ;;
        "")
            usage
            ;;
        *)
            echo "Unrecognized '$1' flag or argument"
            echo "Try 'volumectl -h' for more information"
            ;;
    esac
fi

