# PrtmPhlps's Dotfiles
# Source: https://github.com/PrtmPhlp/Dotfiles
#          _
#  _______| |__  _ __ ___
# |_  / __| '_ \| '__/ __|
#  / /\__ \ | | | | | (__
# /___|___/_| |_|_|  \___|

#S:------------------------------------------------
# ZINIT
export ZDOTDIR="$HOME/.config/zsh"

# Set the directory we want to store zinit and plugins
ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"

# Download Zinit, if it's not there yet
if [ ! -d "$ZINIT_HOME" ]; then
  mkdir -p "$(dirname "$ZINIT_HOME")"
  git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
fi

# Source/Load zinit
source "${ZINIT_HOME}/zinit.zsh"

# ZINIT PLUGINS for MacOS
if [[ "$OSTYPE" == darwin* ]]; then
  zinit ice as"command" from"gh-r" \
    atclone"./starship init zsh > init.zsh; ./starship completions zsh > _starship" \
    atpull"%atclone" src"init.zsh"
  zinit light starship/starship
fi
STARSHIP_LOG=error

# Completion & History
autoload -Uz compinit
setopt extendedglob
local zcd=$HOME/.cache/zsh/zcompdump-$ZSH_VERSION
# Optimize compinit: Run full check only if dump file is missing or older than 24h
if [[ ! -f "$zcd" ]] || [[ -n "$zcd"(#qN.mh+24) ]]; then
  compinit -d "$zcd"
else
  compinit -C -d "$zcd"
fi

# Plugins
zinit wait lucid for \
  zsh-users/zsh-autosuggestions \
  Aloxaf/fzf-tab \
  olets/zsh-window-title \
  MichaelAquilina/zsh-you-should-use

zinit wait lucid for zsh-users/zsh-syntax-highlighting

# Add in snippets
zinit snippet OMZP::sudo
zinit snippet OMZP::command-not-found

# Bash-like navigation
autoload -U select-word-style
select-word-style bash
setopt autocd

# Add functions directory to fpath
fpath=("$ZDOTDIR/functions" $fpath)
zinit cdreplay -q

# History
HISTSIZE=10000
HISTFILE=$HOME/.zsh_history
SAVEHIST=$HISTSIZE
HISTDUP=erase
setopt appendhistory
setopt sharehistory
setopt hist_ignore_space
setopt hist_ignore_all_dups
setopt hist_save_no_dups
setopt hist_ignore_dups
setopt hist_find_no_dups

# Completion styling
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'
zstyle ':completion:*' list-colors '${(s.:.)LS_COLORS}'
zstyle ':completion:*' menu no
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'ls --color $realpath'
zstyle ':fzf-tab:complete:__zoxide_z:*' fzf-preview 'ls --color $realpath'

#S:------------------------------------------------
# EDIT $PATH

pathadd() {
  if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
    PATH="${PATH:+"$PATH:"}$1"
  fi
}

# Call pathadd to include /sbin
pathadd /sbin
pathadd $HOME/.local/bin
#S:------------------------------------------------
# COMMAND CACHE
typeset -A CMD_CACHE
has_cmd() {
  local cmd=$1
  # Only check if not already cached
  if [[ -z ${CMD_CACHE[$cmd]} ]]; then
    if command -v "$cmd" &>/dev/null; then
      CMD_CACHE[$cmd]="true"
    else
      CMD_CACHE[$cmd]="false"
    fi
  fi
  # Return 0 (true) if command exists
  [[ ${CMD_CACHE[$cmd]} == "true" ]]
}

#S:------------------------------------------------
# Shell integrations
[ -f $HOME/dotfiles/scripts/fzf.sh ] && source $HOME/dotfiles/scripts/fzf.sh

if has_cmd fzf; then
  eval "$(fzf --zsh)"
fi

if has_cmd zoxide; then
  eval "$(zoxide init zsh)"
fi


#S:------------------------------------------------
# Specific to Operating System

case "$OSTYPE" in
darwin*)
  #                 ___  ___
  #  _ __  __ _ __ / _ \/ __|
  # | '  \/ _` / _| (_) \__ \
  # |_|_|_\__,_\__|\___/|___/
  #
  # MacOS Specific

  # copy last command:
  alias cpl='fc -ln -1 | awk '\''{$1=$1}1'\'' | pbcopy'
  function pcat() {
    command cat "$1" | pbcopy
    echo "Contents of $1 copied to clipboard."
  }

  # use `trash` if not in Volume (safer deletion)
  function rm {
    # Allow scripts to use real rm via command rm
    if [[ -n $ZSH_SCRIPT ]]; then
      command rm "$@"
      return
    fi
    if [[ "$(pwd)" == /Volumes/* ]]; then
      echo "Detected '/Volumes/*' PATH. Using 'rm' instead of 'trash'" && command rm "$@"
    else
      if has_cmd trash; then
        # Filter out -r, -f, -rf, -fr flags for trash
        local args=()
        for arg in "$@"; do
          [[ "$arg" =~ ^-[rRf]+$ ]] || args+=("$arg")
        done
        command trash "${args[@]}"
      else
        echo "trash not found, using rm -i" && command rm -i "$@"
      fi
    fi
  }

  alias python="/opt/homebrew/bin/python3"
  alias gdu="gdu-go"

  # HomeBrew
  if [[ -f "/opt/homebrew/bin/brew" ]]; then
    export HOMEBREW_NO_AUTO_UPDATE=true
    eval "$(/opt/homebrew/bin/brew shellenv)"
    pathadd /opt/homebrew/bin
    pathadd /opt/homebrew/sbin
    pathadd /opt/homebrew/opt/trash/bin
    pathadd /opt/homebrew/opt/openjdk/bin
    pathadd /opt/homebrew/opt/grep/libexec/gnubin

  fi

  # 1Password SSH Agent
  export SSH_AUTH_SOCK=$HOME/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock
  source $HOME/.config/op/plugins.sh

  ;;
linux*)
  #  _    _
  # | |  (_)_ _ _  ___ __
  # | |__| | ' \ || \ \ /
  # |____|_|_||_\_,_/_\_\

  # Oh-My-Posh
  if has_cmd oh-my-posh; then
    eval "$(oh-my-posh init zsh --config $HOME/dotfiles/.config/zen.toml)"
  fi

  # Nitch
  if has_cmd nitch; then
    nitch
  fi

  # Oh-My-Posh Prompt Name
  case "$(hostname)" in
  "pve") PROMPT_NAME="proxmox" ;;
  "pve2") PROMPT_NAME="pve2" ;;
  "DietPi") PROMPT_NAME="Raspberry" ;;
  "srv-prod-ubuntu-1") PROMPT_NAME="srv-prod-1" ;;
  "srv-prod-ubuntu-2") PROMPT_NAME="srv-prod-2" ;;
  "srv-prod-ubuntu-3") PROMPT_NAME="srv-prod-3" ;;
  "srv-prod-ubuntu-4") PROMPT_NAME="srv-prod-4" ;;
  "srv-prod-ubuntu-5") PROMPT_NAME="srv-prod-5" ;;
  *) PROMPT_NAME="$(whoami)" ;;
  esac
  export PROMPT_NAME

  # export nvim installation PATH
  if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then
    pathadd /opt/nvim-linux-arm64/bin
  elif [ "$(uname -m)" = "x86_64" ]; then
    pathadd /opt/nvim-linux64/bin
    pathadd /opt/nvim-linux-x86_64/bin/
  fi

  # Dietpi ALIASES
  if [ "$(whoami)" = "dietpi" ]; then
    alias temp="sudo vcgencmd measure_temp"
    test -e "${HOME}/dotfiles/scripts/dietpi-alias.sh" && source "${HOME}/dotfiles/scripts/dietpi-alias.sh"
  fi

  ;;
esac

#S:------------------------------------------------
#   ___ _     _          _     _   _ _
#  / __| |___| |__  __ _| |   /_\ | (_)__ _ ___ ___ ___
# | (_ | / _ \ '_ \/ _` | |  / _ \| | / _` (_-</ -_|_-<
#  \___|_\___/_.__/\__,_|_| /_/ \_\_|_\__,_/__/\___/__/
# GLOBAL ALIASES

# Ignore you-should-use message
export YSU_MESSAGE_POSITION="after"
export YSU_IGNORED_ALIASES=("cls", "c" "la" "lla" "lal" "lat" "clat" "g" "ll")

# Disable Less history
export LESSHISTFILE=-
export NODE_REPL_HISTORY=""

# Editor config
if has_cmd nvim; then
  export EDITOR=nvim
  alias vim="nvim"
else
  export EDITOR=vim
fi

# Directory aliases
alias home='cd ~'
alias cd..='cd ..'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'

alias cls="clear"
alias c="clear"

# EZA (or exa / ls)
if has_cmd eza; then
  alias ls="eza --icons=auto"
  alias la="eza -ahl --icons=auto --git --ignore-glob='.DS_Store'"
  alias lla="eza -a --icons=auto --git"
  alias lal="clear ; eza -a --icons=auto --group -s type -r"
  alias lat="eza -ahl --icons=auto --git --tree -L 2 --ignore-glob='.git|node_modules|.venv'"
  alias clat="clear ; eza -ahl --icons=auto --git --tree -L 2 --ignore-glob='.git|node_modules|.venv'"
  alias cla="clear; eza -ahl --icons=auto --git --ignore-glob='.DS_Store'"
elif has_cmd exa; then
  alias ls="exa --icons"
  alias la="exa -ahl --icons"
  alias lla="exa -a --icons"
  alias lal="clear ; exa -a --icons --group"
else
  alias la="ls -ahl"
  alias lal="clear ; la"
fi

# Common aliases
alias scp="scp -r"
alias cd="z"
alias py="python"
alias vpy=".venv/bin/python"
alias vpip=".venv/bin/python -m pip"
if has_cmd python3; then
  alias python="python3"
fi
alias cp="cp -i"
alias mv="mv -i"
alias mkdir='mkdir -p'

# Other
alias nf="neofetch"
alias wget='wget --no-hsts'
alias speedtest-cli="speedtest-cli --secure"
alias speedtest="speedtest-cli --secure"
alias dot="cd ~/dotfiles"

alias zshrc="$EDITOR -c ':setf bash' ~/.zshrc"
alias szshrc="source ~/.zshrc"
alias bashrc="$EDITOR ~/.bashrc"
alias vimrc="$EDITOR ~/.vimrc"

alias dops="dops -a"

#S:------------------------------------------------
# PROGRAMS

# GIT
alias g="git"
function gd() {
  if has_cmd batdiff; then
    batdiff "$@" && batdiff --staged "$@"
  else
    git diff "$@"
  fi
}

alias ga="git add"
alias gco="git commit"

alias gpu="git push"
alias gp="git pull"

alias gb="git branch"
alias gl='git log --graph --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset" --abbrev-commit'
if has_cmd bat; then
  alias gst='awk -vOFS='\'''\'' '\''NR==FNR {all[i++] = $0; difffiles[$1] = $0; next;} ! ($2 in difffiles) {print; next;} {gsub($2, difffiles[$2]); print;} END {if (NR != FNR) {exit;} for (i in all) {print all[i];}}'\'' <(git diff --color --stat=$(($(tput cols) - 3)) HEAD | sed '\''$d; s/^ //'\'') <(git -c color.status=always status -sb) && batdiff && batdiff --staged'
else
  alias gst='awk -vOFS='\'''\'' '\''NR==FNR {all[i++] = $0; difffiles[$1] = $0; next;} ! ($2 in difffiles) {print; next;} {gsub($2, difffiles[$2]); print;} END {if (NR != FNR) {exit;} for (i in all) {print all[i];}}'\'' <(git diff --color --stat=$(($(tput cols) - 3)) HEAD | sed '\''$d; s/^ //'\'') <(git -c color.status=always status -sb)'
fi

alias gia="git add -A"
alias gc="git clone"
alias gcauto="git add -A && git commit -m 'Automatic commit' && git push"
# alias gc='f(){ git clone "$1" && cd "$(basename $1 .git)"; unset -f f; }; f'

# TERRAFORM
alias tf="terraform"
alias tfa="echo -e 'Running \033[1mterraform apply\033[0m\nPress enter to continue...' && read -r && terraform apply --auto-approve"
alias tfd="echo -e 'Running \033[1mterraform destroy\033[0m\nPress enter to continue...' && read -r && terraform destroy --auto-approve"
alias retf="echo -e 'Running \033[1mterraform destroy && terraform apply\033[0m\nPress enter to continue...' && read -r && terraform destroy --auto-approve && terraform apply --auto-approve"
alias tfp="terraform plan"
alias tfv="terraform validate"

# PACKER
alias pab="packer build ."
alias paf="packer fmt -recursive ."

# SSH Cache aliases
SSH_ALIAS_CACHE="$HOME/.cache/zsh/ssh_aliases"
SSH_CONFIG="$HOME/.ssh/config"

if [ -f "$SSH_CONFIG" ]; then
  mkdir -p "$(dirname "$SSH_ALIAS_CACHE")"

  if [ ! -f "$SSH_ALIAS_CACHE" ] || [ "$SSH_CONFIG" -nt "$SSH_ALIAS_CACHE" ]; then
    tmp="${SSH_ALIAS_CACHE}.tmp.$$"

    {
      echo "# generated from ~/.ssh/config"
      grep -i '^host ' "$SSH_CONFIG" \
        | awk '{for (i=2; i<=NF; i++) print $i}' \
        | grep -v '[*?]' \
        | sort -u \
        | while read -r host; do
            echo "alias $host='ssh $host'"
          done
    } > "$tmp"

    # overwrite without prompting, even if mv is aliased
    command mv -f "$tmp" "$SSH_ALIAS_CACHE"
  fi

  source "$SSH_ALIAS_CACHE"
fi

alias hs="ssh homeserver"

alias cknown="$HOME/dotfiles/scripts/clear_known_hosts.sh"
alias vikn="$EDITOR ~/.ssh/known_hosts"
alias vico="$EDITOR ~/.ssh/config"

# DOCKER
alias d="docker"
alias dc="docker compose"
alias dcup="docker compose up -d"
alias dcdown="docker compose down"
alias dclg="docker compose logs -f"
alias dcul="docker compose up -d && docker compose logs -f"
alias dcre="docker compose up -d --force-recreate --remove-orphans"
alias dcrel="docker compose up -d --force-recreate --remove-orphans && docker compose logs -f"
alias dcub="docker compose up -d --build"

# BUN
alias br="bun run"
alias brb="bun run build"
alias brd="bun run dev"
alias brs="bun run start"
alias brp="bun run build && bun run start"
# BUN
if [ -d "$HOME/.bun" ]; then
  pathadd "$HOME/.bun/bin"
  # Load bun completions if available
  [ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun"
fi

#S:------------------------------------------------
# "SMART" ALIASES

# AUTO COMMIT
if has_cmd gum; then
  [ -f "${HOME}/dotfiles/scripts/gum-autogit.sh" ] && alias gauto="${HOME}/dotfiles/scripts/gum-autogit.sh" && alias ggauto="git add . && ${HOME}/dotfiles/scripts/gum-autogit.sh" && alias gchat="op run --no-masking --env-file $HOME/dotfiles/scripts/openai.env $HOME/dotfiles/scripts/gumchat-commit.sh" && alias cmsg="git add . && ${HOME}/dotfiles/scripts/compose-commit.sh"
fi

# CAT, BAT and GLOW
if has_cmd glow && has_cmd bat; then
  function cat() {
    if [[ "$1" == *.md ]]; then
      glow "$@"
    else
      command bat "$@"
    fi
  }
fi
alias ccat="command cat"
#S:------------------------------------------------
# Functions by Christitus

export BAT_THEME="Dracula"
function extract() {
  for archive in "$@"; do
    if [ -f "$archive" ]; then
      # Create a directory based on the archive name
      dir="${archive%.*}"
      mkdir -p "$dir"

      case $archive in
      *.tar.bz2) tar xvjf "$archive" -C "$dir" ;;
      *.tar.gz) tar xvzf "$archive" -C "$dir" ;;
      *.bz2) bunzip2 -c "$archive" >"$dir/$(basename "$archive" .bz2)" ;;
      *.rar) rar x "$archive" "$dir" ;;
      *.gz) gunzip -c "$archive" >"$dir/$(basename "$archive" .gz)" ;;
      *.tar) tar xvf "$archive" -C "$dir" ;;
      *.tbz2) tar xvjf "$archive" -C "$dir" ;;
      *.tgz) tar xvzf "$archive" -C "$dir" ;;
      *.zip) unzip "$archive" -d "$dir" ;;
      *.Z) uncompress -c "$archive" >"$dir/$(basename "$archive" .Z)" ;;
      *.7z) 7z x "$archive" -o"$dir" ;;
      *) echo "don't know how to extract '$archive'..." ;;
      esac
    else
      echo "'$archive' is not a valid file!"
    fi
  done
}

cpg() {
  if [ -d "$2" ]; then
    cp "$1" "$2" && cd "$2"
  else
    cp "$1" "$2"
  fi
}

# Move and go to the directory
mvg() {
  if [ -d "$2" ]; then
    mv "$1" "$2" && cd "$2"
  else
    mv "$1" "$2"
  fi
}

mkdirg() {
  mkdir -p "$1"
  cd "$1"
}

[[ -f $HOME/.zshrc_local ]] && source $HOME/.zshrc_local || true
