{ pkgs, lib, config, ... }:

let

  _tmp_func_name = "_tmp_func_Oaw5aifeeniezeiquonaipheNahthae9caik4Rai"; # pwgen ftw
  mkArgsAlias = alias: ''${_tmp_func_name}() { ${alias}; unset -f ${_tmp_func_name}; }; ${_tmp_func_name}'';

in

{
  # TODO: "bind -s 'set completion-ignore-case on'"
  programs.bash.enable = true;
  #programs.bash.enableCompletion = true;
  programs.bash.shellOptions = [
    # Append to history file rather than replacing it.
    "histappend"
    # check the window size after each command and, if
    # necessary, update the values of LINES and COLUMNS.
    "checkwinsize"
    # Extended globbing.
    "extglob"
    "globstar"
    # Warn if closing shell with running jobs.
    "checkjobs"
  ];
  programs.bash.initExtra = ''
    bind 'set completion-ignore-case on'

    parse_git_branch() {
      git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
    }
    export PS1='\[\033[01;32m\]\u@\h\[\033[01;37m\] \[\033[01;34m\]\W\[\033[33m\]$(parse_git_branch)\[\033[01;32m\]\$\[\033[00m\] '

    # tldr
    if command -v tldr >/dev/null; then
      complete -F _command tldr
    fi

    destore() {
      for dst in "$@"; do
        test -L "$dst" || continue
        # TODO: assert dst is in the store
        src="$(realpath "$dst")"
        if test -d "$src"; then
          (set -x
            rm -v "$dst"
            cp -r --dereference --one-file-system "$src/" "$dst/"
            chmod -R +rw "$dst"
          )
        elif test -f "$src"; then
          (set -x
            rm -v "$dst"
            cp -v "$src" "$dst"
            chmod -v +rw "$dst"
          )
        fi
      done
    }

    _choose_nix_systems() {
      # x86_64-linux aarch64-linux aarch64-darwin x86_64-darwin i686-linux riscv64-linux x86_64-freebsd aarch64-freebsd i686-freebsd riscv64-freebsd
      gum choose --no-limit --ordered --height 15 {linux,darwin,freebsd}-{x86_64,aarch64,i686,riscv64} \
        | sed -E 's/^([^-]*)-([^-]*)$/\2-\1/'
    }

    mnix-build() {
      # TODO: somehow store the out-links
      _choose_nix_systems | xe -j0 -s 'nix-instantiate --system "$1" '"$(printf " %q" "$@")" | xargs nix-build --keep-going --no-out-link
    }
    mnom-build() {
      # TODO: somehow store the out-links
      _choose_nix_systems | xe -j0 -s 'nix-instantiate --system "$1" '"$(printf " %q" "$@")" | xargs nom-build --keep-going --no-out-link
    }
    mnixpkgs-review() {
      # TODO: use /run/user/...
      # mkdir -p /dev/shm/nixpkgs-review
      # ln -sfn /dev/shm/nixpkgs-review $HOME/.cache/nixpkgs-review
      nixpkgs-review --systems "$(_choose_nix_systems | xargs)" "$@"
    }

  '';

  imports = [ ../modules/jump.nix ];
  programs.jump.enableBash = true;

  programs.nix-index.enable = true;
  programs.nix-index-database.comma.enable = true; # via nix-index-database flake
  #programs.command-not-found.enable = false; # mutex with nix-index

  programs.fzf = {
    enable = true; # TODO: does this conflict with system-wide setup?

    # alt-c
    changeDirWidgetCommand = "fd --type d"; # respects .gitignore
    changeDirWidgetOptions = [ "--preview 'tree -C {} | head -200'" ];

    # ctrl-t
    fileWidgetCommand = "fd --type f"; # respects .gitignore
    fileWidgetOptions = [
      #"--preview 'head {}'"
      # https://github.com/junegunn/fzf/discussions/3363#discussioncomment-6419463
      "--bind 'ctrl-a:reload:eval $FZF_DEFAULT_COMMAND --no-ignore'"
    ];

    # ctrl-r
    #historyWidgetOptions = [ "--sort" "--exact" ];
  };

  programs.eza.enable = true;
  programs.eza.enableAliases = lib.mkIf (lib.versionOlder config.home.version.release "24.05") true;

  #programs.zoxide.enable = true;
  #programs.zoxide.options = [ "--cmd cd --cmd dc" ];

  programs.carapace.enable = true; # completions

  # i can't type
  home.shellAliases.sl = "eza";
  #home.shellAliases.dc = "cd";

  programs.direnv.enable = true;
  programs.direnv.nix-direnv.enable = true;

  programs.tealdeer.enable = true;
  programs.tealdeer.settings.updates.auto_update = true;

  # just use ncdu lol
  home.shellAliases.dush = "du -shc * | sort -h";
  home.shellAliases.dushd = "du -shc * .[!.]?* | sort -h";

  home.shellAliases.open = "xdg-open";

  home.shellAliases.grep = "grep --color";
  home.shellAliases.diff = "diff -u --color"; # eyo
  home.shellAliases.ip = "ip -br -color";
  home.shellAliases.rssh = "ssh -l root";
  home.shellAliases.sudo = "sudo "; # makes sudo support aliases
  home.shellAliases.watch = "watch -c "; # parse colors
  home.shellAliases.xargs = "xargs ";

  # old -> new
  home.shellAliases.vimv = "edir";

  # Be conservative with files
  # --preserver-root is for GNU versions, preventing changing perms on /
  home.shellAliases.chown = "chown --preserve-root";
  home.shellAliases.chmod = "chmod --preserve-root";
  home.shellAliases.chgrp = "chgrp --preserve-root";
  home.shellAliases.rm = "rm --preserve-root";
  # prompt if deleting more than 3 files at a time
  #home.shellAliases.rm = "rm -i";
  #home.shellAliases.mv = "mv -i";
  #home.shellAliases.cp = "cp -i";

  home.shellAliases.inom  = mkArgsAlias ''nom "$@" --system i686-linux -j0'';
  home.shellAliases.inix  = mkArgsAlias ''nix "$@" --system i686-linux -j0'';
  home.shellAliases.rnom  = mkArgsAlias ''nom "$@" --system riscv64-linux -j0'';
  home.shellAliases.rnix  = mkArgsAlias ''nix "$@" --system riscv64-linux -j0'';
  home.shellAliases.fnom  = mkArgsAlias ''nom "$@" --system x86_64-freebsd -j0'';
  home.shellAliases.fnix  = mkArgsAlias ''nix "$@" --system x86_64-freebsd -j0'';
  home.shellAliases.anom  = mkArgsAlias ''nom "$@" --system aarch64-linux -j0'';
  home.shellAliases.anix  = mkArgsAlias ''nix "$@" --system aarch64-linux -j0'';
  home.shellAliases.dnom  = mkArgsAlias ''nom "$@" --system x86_64-darwin -j0'';
  home.shellAliases.dnix  = mkArgsAlias ''nix "$@" --system x86_64-darwin -j0'';
  home.shellAliases.danom = mkArgsAlias ''nom "$@" --system aarch64-darwin -j0'';
  home.shellAliases.danix = mkArgsAlias ''nix "$@" --system aarch64-darwin -j0'';

  home.shellAliases.inom-build  = "nom-build --system i686-linux -j0";
  home.shellAliases.inix-build  = "nix-build --system i686-linux -j0";
  home.shellAliases.rnom-build  = "nom-build --system riscv64-linux -j0";
  home.shellAliases.rnix-build  = "nix-build --system riscv64-linux -j0";
  home.shellAliases.fnom-build  = "nom-build --system x86_64-freebsd -j0";
  home.shellAliases.fnix-build  = "nix-build --system x86_64-freebsd -j0";
  home.shellAliases.anom-build  = "nom-build --system aarch64-linux -j0";
  home.shellAliases.anix-build  = "nix-build --system aarch64-linux -j0";
  home.shellAliases.dnom-build  = "nom-build --system x86_64-darwin -j0";
  home.shellAliases.dnix-build  = "nix-build --system x86_64-darwin -j0";
  home.shellAliases.danom-build = "nom-build --system aarch64-darwin -j0";
  home.shellAliases.danix-build = "nix-build --system aarch64-darwin -j0";

  home.shellAliases.kaomoji = "curl -s 'https://kaomoji.ru/en/' | htmlq tr td span --text | grep . | shuf | head -n1";

  home.packages = lib.filter (x: x != null) (with pkgs; [
    rsync
    bind.dnsutils # dig
    dogdns # dog
    edir # better vimv
    curl
    wget

    wakeonlan

    #tldr
    stress
    entr
    axel aria aria2
    xe # xargs alternative
    sd # sed alternative
    fd # find alternative
    silver-searcher # 'ag'
    ripgrep # 'rg'
    comby
    gron
    jq
    fx
    yq # includes xmlq and tomlq
    fq # binary jq
    (pkgs.jnv or unstable.jnv or null)
    htmlq
    just # justfile
    gum
    sysz
    du-dust # du alternative
    duf # df alternative
    ncdu # Disk usage analyzer with an ncurses interface
    xplr # tui file explorer
    aha (pkgs.colorized-logs or unstable.colorized-logs)
  ]);

}