#!/usr/bin/env bash
platform="$(uname)"

# first check the version of bash
if ! type mapfile &> /dev/null; then
    echo "error: extrakto needs a newer Bash"
    if [[ $platform == Darwin ]]; then
        echo "On macOS you need to install/update it with Homebrew."
        echo "exec: brew install bash"
    fi
    read # pause
    exit 1
fi

PRJ_URL=https://github.com/laktak/extrakto
current_dir="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
trigger_pane=$1
launch_mode=$2
source "$current_dir/helpers.sh"
extrakto="$current_dir/../extrakto.py"

declare -Ar COLORS=(
    [RED]=$'\033[0;31m'
    [GREEN]=$'\033[0;32m'
    [BLUE]=$'\033[0;34m'
    [PURPLE]=$'\033[0;35m'
    [CYAN]=$'\033[0;36m'
    [WHITE]=$'\033[0;37m'
    [YELLOW]=$'\033[0;33m'
    [OFF]=$'\033[0m'
    [BOLD]=$'\033[1m'
)

# options; note some of the values can be overwritten by capture()
grab_area=$(get_option "@extrakto_grab_area")
clip_tool=$(get_option "@extrakto_clip_tool")
clip_tool_run=$(get_option "@extrakto_clip_tool_run")
editor=$(get_option "@extrakto_editor")
fzf_tool=$(get_option "@extrakto_fzf_tool")
open_tool=$(get_option "@extrakto_open_tool")
copy_key=$(get_option "@extrakto_copy_key")
insert_key=$(get_option "@extrakto_insert_key")
filter_key=$(get_option "@extrakto_filter_key")
open_key=$(get_option "@extrakto_open_key")
edit_key=$(get_option "@extrakto_edit_key")
grab_key=$(get_option "@extrakto_grab_key")
help_key=$(get_option "@extrakto_help_key")
fzf_layout=$(get_option "@extrakto_fzf_layout")
fzf_unset_default_opts=$(get_option "@extrakto_fzf_unset_default_opts")

capture_pane_start=$(get_capture_pane_start "$grab_area")
original_grab_area=${grab_area} # keep this so we can cycle between alternatives on fzf

# avoid side effects from FZF_DEFAULT_OPTS
if [[ $fzf_unset_default_opts == "true" ]]; then
    unset FZF_DEFAULT_OPTS
fi

if [[ "$clip_tool" == "auto" ]]; then
    case "$platform" in
        'Linux')
            if [[ $(cat /proc/sys/kernel/osrelease) =~ Microsoft|microsoft ]]; then
                clip_tool='clip.exe'
            elif [[ $XDG_SESSION_TYPE == "wayland" ]]; then
                clip_tool='wl-copy'
            else
                clip_tool='xclip -i -selection clipboard >/dev/null'
            fi
            ;;
        'Darwin') clip_tool='pbcopy' ;;
        *) ;;
    esac
fi

if [[ "$open_tool" == "auto" ]]; then
    case "$platform" in
        'Linux') open_tool='xdg-open >/dev/null' ;;
        'Darwin') open_tool='open' ;;
        *) open_tool='' ;;
    esac
fi

if [[ -z $editor ]]; then
    editor="${EDITOR:-vi}"
fi

copy() {
    if [[ "$clip_tool_run" == "fg" ]]; then
        # run in foreground as OSC-52 copying won't work otherwise
        tmux set-buffer -- "$1"
        tmux run-shell "tmux show-buffer|$clip_tool"
    elif [[ "$clip_tool_run" == "tmux_osc52" ]]; then
        # use native tmux 3.2 OSC 52 functionality
        tmux set-buffer -w -- "$1"
    else
        # run in background as xclip won't work otherwise
        tmux set-buffer -- "$1"
        tmux run-shell -b "tmux show-buffer|$clip_tool"
    fi
}

open() {
    if [[ -n "$open_tool" ]]; then
        tmux run-shell -b "cd -- $PWD; $open_tool $1"
        return 0
    fi
}

capture_panes() {
    local pane captured
    captured=""

    if [[ $grab_area =~ ^window\  ]]; then
        for pane in $(tmux list-panes -F "#{pane_active}:#{pane_id}"); do
            # exclude the active (for split) and trigger panes
            # in popup mode the active and tigger panes are the same
            if [[ $pane =~ ^0: && ${pane:2} != "$trigger_pane" ]]; then
                captured+="$(tmux capture-pane -pJS ${capture_pane_start} -t ${pane:2})"
                captured+=$'\n'
            fi
        done
    fi

    captured+="$(tmux capture-pane -pJS ${capture_pane_start} -t $trigger_pane)"

    echo "$captured"
}

has_single_pane() {
    local num_panes
    num_panes=$(tmux list-panes | wc -l)
    if [[ $launch_mode == popup ]]; then
        [[ $num_panes == 1 ]]
    else
        [[ $num_panes == 2 ]]
    fi
}

show_fzf_error() {
    echo "error: unable to extract - check/report errors above"
    echo "You can also set the fzf path in options (see readme)."
    read # pause
}

capture() {
    local mode header_tmpl header out res key text query

    mode=$(get_next_mode "initial")

    header_tmpl="${COLORS[BOLD]}${insert_key}${COLORS[OFF]}=insert"
    header_tmpl+=", ${COLORS[BOLD]}${copy_key}${COLORS[OFF]}=copy"
    [[ -n "$open_tool" ]] && header_tmpl+=", ${COLORS[BOLD]}${open_key}${COLORS[OFF]}=open"
    header_tmpl+=", ${COLORS[BOLD]}${edit_key}${COLORS[OFF]}=edit"
    header_tmpl+=", ${COLORS[BOLD]}${filter_key}${COLORS[OFF]}=filter [${COLORS[YELLOW]}${COLORS[BOLD]}:filter:${COLORS[OFF]}]"
    header_tmpl+=", ${COLORS[BOLD]}${grab_key}${COLORS[OFF]}=grab [${COLORS[YELLOW]}${COLORS[BOLD]}:ga:${COLORS[OFF]}]"
    header_tmpl+=", ${COLORS[BOLD]}${help_key}${COLORS[OFF]}=help"

    get_cap() {
        case "$mode" in
            "all")
                capture_panes | $extrakto --warn-empty --alt --all --name -r
                ;;
            "line")
                capture_panes | $extrakto --warn-empty -r --lines
                ;;
            "path")
                capture_panes | $extrakto --warn-empty -r --paths
                ;;
            "url")
                capture_panes | $extrakto --warn-empty -r --urls
                ;;
            "word")
                capture_panes | $extrakto --warn-empty -r --words
                ;;
            *)
                # custom filters
                capture_panes | $extrakto --warn-empty -ra $mode
                ;;

        esac
    }

    while true; do
        header=$header_tmpl
        header=${header/:ga:/$grab_area}
        header=${header/:filter:/$mode}
        header=${header//ctrl-/^}

        # for troubleshooting add
        # tee /tmp/stageN | \
        # between the commands
        out="$(get_cap \
            | $fzf_tool \
                --multi \
                --print-query \
                --query="$query" \
                --header="$header" \
                --expect=${insert_key},${copy_key},${filter_key},${edit_key},${open_key},${grab_key},${help_key},ctrl-c,esc \
                --tiebreak=index \
                --layout="$fzf_layout" \
                --no-preview \
                --no-info)"
        res=$?
        {
            read query
            read key
            mapfile -t selection
        } <<< "$out"

        if [[ $res -gt 0 && -z "$key" ]]; then
            show_fzf_error
            exit 1
        fi

        case "$mode" in
            all)
                text="${selection[@]#*: }"
                ;;
            line)
                IFS=$'\n' text="${selection[*]}"
                ;;
            *)
                text="${selection[@]}"
                ;;
        esac

        case "$key" in
            "${copy_key}")
                copy "$text"
                return 0
                ;;

            "${insert_key}")
                tmux set-buffer -- "$text"
                tmux paste-buffer -p -t $trigger_pane
                return 0
                ;;

            "${filter_key}")
                mode=$(get_next_mode $mode)
                ;;

            "${grab_key}")
                # cycle between options like this:
                # recent -> full -> window recent -> window full -> custom (if any) -> recent ...
                if [[ $grab_area == "recent" ]]; then
                    if has_single_pane; then
                        grab_area="full"
                    else
                        grab_area="window recent"
                    fi
                elif [[ $grab_area == "window recent" ]]; then
                    grab_area="full"
                elif [[ $grab_area == "full" ]]; then
                    if has_single_pane; then
                        grab_area="recent"

                        if [[ ! "$original_grab_area" =~ ^(window )?(recent|full)$ ]]; then
                            grab_area="$original_grab_area"
                        fi
                    else
                        grab_area="window full"
                    fi
                elif [[ $grab_area == "window full" ]]; then
                    grab_area="recent"

                    if [[ ! "$original_grab_area" =~ ^(window )?(recent|full)$ ]]; then
                        grab_area="$original_grab_area"
                    fi
                else
                    grab_area="recent"
                fi

                capture_pane_start=$(get_capture_pane_start "$grab_area")
                ;;

            "${open_key}")
                open "$text"
                return 0
                ;;

            "${edit_key}")
                tmux send-keys -t $trigger_pane "$editor -- $text" 'C-m'
                return 0
                ;;

            "${help_key}")
                clear
                less -+EF $(realpath "$current_dir/../HELP.md")

                echo -e "\nSince the help page is not 'extrakt'-able:"
                read -p "Do you wish to [o]pen or [c]opy the GitHub page or [a]bort? [ocA]" -d'' -s -n1 confirm
                if [[ $confirm == o ]]; then
                    open $PRJ_URL
                elif [[ $confirm == c ]]; then
                    copy $PRJ_URL
                fi
                ;;

            *)
                return 0
                ;;
        esac
    done
}

# Entry

if [[ $launch_mode != popup ]]; then
    # check terminal size, zoom pane if too small
    lines=$(tput lines)
    if [[ $lines -lt 7 ]]; then
        tmux resize-pane -Z
    fi
fi

capture
