function cd_to() {
    setopt localoptions pipefail no_aliases 2> /dev/null
    local dir=$1
    if [[ -z "$dir" ]]; then
        zle redisplay
        return 0
    fi
    zle push-line # Clear buffer. Auto-restored on next prompt.
    cd $dir
    zle accept-line
    local ret=$?
    unset dir # ensure this doesn't end up appearing in prompt expansion
    zle reset-prompt
}

function find_local() {
    fd . -t $1 | fzy -l 20
}

function find_global() {
    file_type=$1
    FZY_CACHE=~/.cache/fzy_paths_$file_type
    if [ -f $FZY_CACHE ]; then
        if [ $(stat -c %Y $FZY_CACHE) -lt $(date +%s -d '-1 day') ]; then
            rm $FZY_CACHE
        fi
    fi
    if [ ! -f $FZY_CACHE ]; then
        PATHS=""
        search_dirs=(~/.dotfiles/ ~/Workspace/ ~/Containers/ /home/server/Storage/Thomas/)
        for i in "$search_dirs[@]"; do
            if [ -d $i ]; then
                PATHS="$PATHS\n$i"
                if [ "$(hostname)" = "mallorea" ]; then
                    PATHS+="\n$(fd . $i -t $file_type -d 8)"
                else
                    PATHS+="\n$(ssh mallorea fd . $i -t $file_type -d 8)"
                fi
            fi
        done
        echo -e "$PATHS" > $FZY_CACHE
    fi
    file="$(cat $FZY_CACHE | fzy -l 20)"
    echo "$file" | cat - $FZY_CACHE | awk '!x[$0]++' > /tmp/fzy_paths_$file_type && mv /tmp/fzy_paths_$file_type $FZY_CACHE
    echo "$file"
}

function open_path() {
    file_type=$1
    search_fn=$2
    selection="$($search_fn $file_type)"
    if [ "$selection" = "" ]; then
        zle reset-prompt
        return
    fi
    if [ "$LBUFFER" = "" ]; then
        if [ "$file_type" = "d" ]; then
            cd_to "$selection"
        else
            selection=$(realpath "$selection")
            parent=$(dirname "$selection")
            cd_to "$parent"
            nvim "$selection"
        fi
    else
        emulate -L zsh
        zle -I
        LBUFFER="${LBUFFER}\"$selection\""
        zle reset-prompt
    fi
}

function open_global_path_d() { open_path d find_global }
function open_global_path_f() { open_path f find_global }
function open_local() { open_path f find_local }

zle -N push_local_files
zle -N find_local_directories

key[Home]="${terminfo[khome]}"
key[End]="${terminfo[kend]}"
key[Insert]="${terminfo[kich1]}"
key[Backspace]="${terminfo[kbs]}"
key[Delete]="${terminfo[kdch1]}"
key[Up]="${terminfo[kcuu1]}"
key[Down]="${terminfo[kcud1]}"
key[Left]="${terminfo[kcub1]}"
key[Right]="${terminfo[kcuf1]}"
key[PageUp]="${terminfo[kpp]}"
key[PageDown]="${terminfo[knp]}"
key[Shift-Tab]="${terminfo[kcbt]}"

# setup key accordingly
[[ -n "${key[Home]}"      ]] && bindkey -- "${key[Home]}"       beginning-of-line
[[ -n "${key[End]}"       ]] && bindkey -- "${key[End]}"        end-of-line
[[ -n "${key[Insert]}"    ]] && bindkey -- "${key[Insert]}"     overwrite-mode
[[ -n "${key[Backspace]}" ]] && bindkey -- "${key[Backspace]}"  backward-delete-char
[[ -n "${key[Delete]}"    ]] && bindkey -- "${key[Delete]}"     delete-char
[[ -n "${key[Up]}"        ]] && bindkey -- "${key[Up]}"         up-line-or-history
[[ -n "${key[Down]}"      ]] && bindkey -- "${key[Down]}"       down-line-or-history
[[ -n "${key[Left]}"      ]] && bindkey -- "${key[Left]}"       backward-char
[[ -n "${key[Right]}"     ]] && bindkey -- "${key[Right]}"      forward-char
[[ -n "${key[PageUp]}"    ]] && bindkey -- "${key[PageUp]}"     beginning-of-buffer-or-history
[[ -n "${key[PageDown]}"  ]] && bindkey -- "${key[PageDown]}"   end-of-buffer-or-history
[[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}"  reverse-menu-complete

autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
[[ -n "${key[Up]}"   ]] && bindkey -- "${key[Up]}"   up-line-or-beginning-search
[[ -n "${key[Down]}" ]] && bindkey -- "${key[Down]}" down-line-or-beginning-search

zle -N fzf-history-widget
bindkey -M vicmd "^R" fzf-history-widget
bindkey -M viins "^R" fzf-history-widget
bindkey -M emacs "^R" fzf-history-widget

function register_key() {
    zle -N $2
    bindkey "^$1" $2
    bindkey -M emacs "^$1" $2
    bindkey -M vicmd "^$1" $2
    bindkey -M viins "^$1" $2
}

register_key "T" open_global_path_d
register_key "E" open_global_path_f
register_key "W" open_local
