#!/usr/bin/env fish

set -U EDITOR vim
set -U VISUAL vim
set -U LANG en_US
set -U LC_ALL en_US.UTF-8

if status is-interactive
    set -gx COLORTERM truecolor
end

set -U fish_greeting # Hide greeting
fish_vi_key_bindings
function fish_mode_prompt; end # Hide vi mode
function fish_prompt -d "Custom prompt"
    # Define shorthands for hostnames.
    set full_hostname (hostname)
    switch $full_hostname
        case "anarres"
            set shorthand_name "𝖆"
        case "marain"
            set shorthand_name "🜲 "
        case "localhost"
            set shorthand_name "⌘"
        case '*'
            set shorthand_name $full_hostname  # Fallback to full hostname
    end

    printf '%s%s%s:%s%s%s:%s%s%s ' \
        (set_color "#fffae0") $shorthand_name (set_color "#333333") (set_color "#7fb1f5") (prompt_pwd) (set_color "#333333") (set_color "#484848") (fish_git_prompt %s) (set_color normal)
end

set PATH $HOME/.bin $HOME/.local/bin $HOME/.cargo/bin /usr/sbin /var/lib/flatpak/exports/bin/ $PATH

if type -q gsettings
    gsettings set org.gnome.desktop.interface color-scheme prefer-dark
end

if test -f ~/.local/bin/mise
    # node, python
    ~/.local/bin/mise activate fish | source
    if type -q npm
        set -gx NODE_PATH (npm root -g)
    end
end

fzf --fish | source
zoxide init fish | source

# Easier navigation
abbr -a ,, "cd .."
abbr -a ,,, "cd ../.."
abbr -a ,,,, "cd ../../.."
abbr -a ,,,,, "cd ../../../.."

# To avoid accidentally overwriting files
abbr -a mv "mv -i"

# Smart case ripgrep
abbr -a rg "rg -S"

# Easier than z
abbr -a e "z"

# Git
abbr -a gd "git diff"
abbr -a ga "git add"
abbr -a gap "git add -p"
abbr -a gaa "git add -A"
abbr -a gc "git commit"
abbr -a gp "git push"
abbr -a gpl "git pull"
abbr -a gm "git merge --no-ff"
abbr -a gch "git checkout"
abbr -a gcb "git checkout -b"
abbr -a gbd "git branch -d"
abbr -a gds "git diff --staged"
abbr -a gsu "git submodule foreach git pull origin master"

# Shortcuts
abbr -a v "vi ."
abbr -a b "bat"
abbr -a j "just"
abbr -a c "cargo"
abbr -a n "cd ~/notes"
abbr -a w "cd ~/work"
abbr -a p "cd ~/projects"
abbr -a dl "cd ~/downloads"
abbr -a dots "cd ~/.dots"
abbr -a evi "cd ~/.dots/dots/nvim; vi init.lua"
abbr -a ytdl "yt-dlp --remote-components ejs:github -f 'bv[height<=1080]+ba'"
abbr -a ytdlmp3 "yt-dlp --remote-components ejs:github --extract-audio --audio-format mp3"
abbr -a publish "port build spaceandtimes; port sync spaceandtimes ftseng@starbase:/srv/spaceandtimes"

function ,
	set tmp (mktemp -t "yazi-cwd.XXXXXX")
	yazi $argv --cwd-file="$tmp"
	if set cwd (command cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
		builtin cd -- "$cwd"
	end
	rm -f -- "$tmp"
end

function rand -d "Generate random string"
    cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1
end

function flac2mp3
    set --local input $argv[1]
    set --local output (path change-extension mp3 $input)
    ffmpeg -i "$input" -ab 320k -map_metadata 0 -id3v2_version 3 "$output"
    echo "$output"
end

function mkv2mp4
    set --local input $argv[1]
    set --local output (path change-extension mp4 $input)
    ffmpeg -i "$input" -preset veryfast -c:v libx264 -c:a aac "$output"
end

function mp32m4a
    set --local input $argv[1]
    set --local output (path change-extension m4a $input)
    ffmpeg -i "$input" -c:a libfdk_aac -vbr 4 "$output"
end

function shrinkvid
    # libx264 is way faster than libx265 but maybe doesn't get as small
    # higher crf -> lower quality
    set --local input $argv[1]
    set --local output (path change-extension sm.mp4 $input)
    ffmpeg -i "$input" -vf "scale='if(gt(ih,720),trunc(oh*a/2)*2,iw)':'if(gt(ih,720),720,ih)'" -vcodec libx264 -crf 23 -preset fast -c:a aac "$output"
end

function mergevids
    if test (count $argv) -lt 2
        echo "Usage: mergevids [files...] output.mp4"
        return 1
    end

    set output $argv[-1]
    set inputs $argv[1..-2]

    set tmpfile (mktemp)
    for file in $inputs
        echo "file '$PWD/$file'" >> $tmpfile
    end

    ffmpeg -f concat -safe 0 -i $tmpfile -c copy $output

    rm $tmpfile
end

# Embed co-located *.srt files into the input video.
# Needed for minidlna to serve subtitles correctly.
function muxsubs --argument input_file
    set -l base_name (string replace -r '\.[^.]+$' '' $input_file)
    set -l output_file "$base_name.Subbed.mkv"

    set -l inputs
    set -l maps "-map" "0" # Always map the base video/audio
    set -l count 1

    # Loop through all SRTs to build the flags
    for srt in *.srt
        set -a inputs -i "$srt"
        set -a maps -map "$count:0"
        set count (math $count + 1)
    end

    ffmpeg -i "$input_file" $inputs $maps -c copy -max_interleave_delta 0 "$output_file"
end

function gitsizes
    git rev-list --objects --all \
      | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
      | awk '/^blob/ {print $3, $4}' \
      | sort -nr \
      | head -20
end

# Bindings:
#   ctrl-a: enable jump

set -Ux FZF_DEFAULT_OPTS "\
    --exact \
    --info=hidden \
    --color=bg+:#262626,fg+:#eac9f5,hl:green,hl+:green,gutter:#121212,pointer:magenta,prompt:green \
    --bind=ctrl-a:jump-accept"

# ctrl-l
function _dive
    # -t d: directories only
    # -d 5: max depth 8
    set --local choice $(fd -t d -d 8 . . | fzf);
        and cd $choice;
        and commandline -f repaint
end
bind -M insert \cl '_dive'
bind -M default \cl '_dive'

# ctrl-a
function _seek
    # -t d: directories only
    # -d 8: max depth 8
    set --local choice $(fd -t d -d 8 --exclude musics . ~ | fzf);
        and cd $choice;
        and commandline -f repaint
end
bind -M insert \ct '_seek'
bind -M default \ct '_seek'

# ctrl-s
# https://stackoverflow.com/a/76799272
function _pick_and_insert
    set --local path $(fd . ~ | fzf); and commandline -i $path
end
bind -M insert \cs '_pick_and_insert'
bind -M default \cs '_pick_and_insert'

# ctrl-e to accept autosuggestion
bind -M insert \ce accept-autosuggestion

# delete previous argument
bind -M insert ctrl-x backward-kill-token

# move to previous/next argument
bind -M insert ctrl-comma backward-token
bind -M insert ctrl-\' forward-token

# ctrl-v to edit commend in $EDITOR
bind -M insert \cv edit_command_buffer
bind -M default \cv edit_command_buffer

# Color theme
# Use `msgcat --color=test` to see the colors.
set -Ux fish_color_normal white
set -Ux fish_color_command green
set -Ux fish_color_param blue
set -Ux fish_color_quote magenta
set -Ux fish_color_redirection --bold blue
set -Ux fish_color_end brblue
set -Ux fish_color_error red
set -Ux fish_color_comment white
set -Ux fish_color_selection brblack
set -Ux fish_color_search_match --background=black
set -Ux fish_color_operator --bold yellow
set -Ux fish_color_valid_path --bold magenta
set -Ux fish_color_escape cyan
set -Ux fish_color_cwd --bold brblue
set -Ux fish_color_autosuggestion brblack
set -Ux fish_color_user --bold brcyan
set -Ux fish_color_host --bold brgreen
set -Ux fish_color_host_remote --bold red
set -Ux fish_color_cancel red

# Needed for GPG to work correctly
set -x GPG_TTY (tty)
set -e GPG_AGENT_INFO
gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1

# Launch WM from the login tty.
if test -z "$DISPLAY"; and test (tty) = "/dev/tty1"
    exec niri-session -l
end
