#!/usr/bin/env bash

set -o pipefail

# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
# only accepts ESC backslash for ST.
function print_osc() {
    if [[ $TERM == screen* || $TERM == tmux* ]] ; then
        printf "\033Ptmux;\033\033]"
    else
        printf "\033]"
    fi
}

# More of the tmux workaround described above.
function print_st() {
    if [[ $TERM == screen* || $TERM == tmux* ]] ; then
        printf "\a\033\\"
    else
        printf "\a"
    fi
}

function get_b64_version() {
    if [[ -z "${BASE64_VERSION+x}" ]]; then
        BASE64_VERSION=$(base64 --version 2>&1)
        export BASE64_VERSION
    fi
}

function b64_encode() {
    get_b64_version
    if [[ $BASE64_VERSION =~ GNU ]]; then
        # Disable line wrap
        base64 -w0
    else
        base64
    fi
}

function b64_decode() {
    get_b64_version
    if [[ $BASE64_VERSION =~ fourmilab ]]; then
        BASE64_ARG=-d
    elif [[ $BASE64_VERSION =~ GNU ]]; then
        BASE64_ARG=-di
    else
        BASE64_ARG=-D
    fi
    base64 $BASE64_ARG
}

function error() {
    errcho "ERROR: $*"
}

function errcho() {
    echo "$@" >&2
}

function show_help() {
    errcho
    errcho "Usage: it2getvar variable_name"
    errcho
    errcho "Output value of the iTerm2 variable"
    errcho
    errcho "See the Variables Reference for information about built-in iTerm2 variables:"
    errcho "  -> https://iterm2.com/documentation-variables.html"
    errcho
}

function check_dependency() {
    if ! (builtin command -V "$1" >/dev/null 2>&1); then
        error "missing dependency: can't find $1"
        exit 1
    fi
}

# get_variable variable_name
#
# This function uses POSIX standard synonym for the controlling terminal
# associated with the current process group - /dev/tty. It is useful for programs
# that wish to be sure of writing or reading data from the terminal
# no matter how STDIN/STDOUT/STDERR has been redirected.
function get_variable() {
    trap 'cleanup' EXIT
    stty -echo < /dev/tty
    exec 9<> /dev/tty
    print_osc >&9
    printf "1337;ReportVariable=%s" "$(echo -n "$1" | b64_encode)" >&9
    print_st >&9
    read -r -t 5 -d $'\a' iterm_response <&9
    exec 9>&-
    stty echo < /dev/tty
    [[ "$iterm_response" =~ ReportVariable= ]] || {
        error "Failed to read response from iTerm2"
        exit 2
    }
    echo "$(b64_decode <<< ${iterm_response#*=})"
}

function cleanup() {
    stty echo < /dev/tty
}

# Show help if no arguments
if [ $# -eq 0 ]; then
    show_help
    exit
fi

check_dependency stty
check_dependency base64

# Process command line arguments
case "$1" in
    -h|--h|--help)
        show_help
        exit
        ;;
    -*)
        error "Unknown option: $1"
        show_help
        exit 1
        ;;
    *)
        [[ -z "$1" ]] && error "Variable name can't be empty" && exit 1
        get_variable "$1"
        ;;
esac

exit 0
