{ config
, pkgs
, lib
, ...
}:
with builtins;
with lib.attrsets;
let
  scripts = (import ./scripts.nix) pkgs;
  aliases = with scripts; {
    "cp-mov" = cp-media "mov" "movies";
    "cp-ser" = cp-media "ser" "shows";
    "cp-ani" = cp-media "ani" "anime";
    "dumpasm" = "${pkgs.custom.dumpasm}/bin/dumpasm";
    "p" = builtins.trace calc calc;
    "s" = "systemctl";
    "j" = "journalctl";
    "ju" = "journalctl -u";
    "jfu" = "journalctl -fu";
    "ls" = "${pkgs.eza}/bin/eza --git";
    "ll" = "${pkgs.eza}/bin/eza --git";
    "lt" = "${pkgs.eza}/bin/eza --long --tree -L 3";
    "open" = "${pkgs.xdg-utils}/bin/xdg-open";
    "cb" = "${pkgs.wl-clipboard-rs}/bin/wl-copy";
    "cat" = "${pkgs.bat}/bin/bat";

    # "pull" = "${pkgs.git}/bin/git pull";
    # "push" = "${pkgs.git}/bin/git push";
    # "commit" = "${pkgs.git}/bin/git commit";
    # "add" = "${pkgs.git}/bin/git add";
    # "patch" = "${pkgs.git}/bin/git add -p";
    # "amend" = "${pkgs.git}/bin/git commit --amend";
    # "log" = "${pkgs.git}/bin/git log --all --graph --decorate";
    # "st" = "${pkgs.git}/bin/git status";
    # "checkout" = "${pkgs.git}/bin/git checkout";
    # "rebase" = "${pkgs.git}/bin/git rebase";
    # "stash" = "${pkgs.git}/bin/git stash";

    "edit" = "jj edit";
    "old" = "jj edit @-";
    "new" = "jj edit @+";
    "rebase" = "jj rebase";
    "pull" = "jj git fetch; jj catchup";
    "msg" = "jj describe -m";
    "branch" = "jj bookmark set";
    "stat" = "jj status";
    "push" = "jj git push";

    "tidy" = "x test tidy --bless";
    "ui" = "x test tests/ui/";

    "f" = "nautilus --no-desktop . &";
  };
  # extracting any compressed format
  extract = ''
    function extract -a file -d "decompress a file"
      if not test -f $file
        echo "'$file' is not a valid file"
        return 1
      end
      switch $file
        # tar can automatically figure out how to decompress
        case '*.{tar,tar.{bz2,zst,gz,xz},tbz2,tgz'; ${pkgs.gnutar}/bin/tar xf $file; end
        case '*.bz2'; bunzip2 $file; end
        case '*.rar'; unrar e $file; end
        case '*.gz'; gunzip $file; end
        case '*.zip'; ${pkgs.unzip}/bin/unzip $file; end
        case '*.Z'; uncompress $file; end
        case '*.7z'; 7z x $file; end
        case '*';
          echo "'$file' cannot be extracted"
          return 1
      end
    end
  '';
in
{
  programs = {
    atuin = {
      enable = true;
      enableFishIntegration = true;

      settings = {
        filter_mode_shell_up_key_binding = "directory";
        exit_mode = "return-original";

        workspaces = true;
      };
    };

    zoxide = {
      enable = true;
      enableFishIntegration = true;
    };

    direnv = {
      enable = true;
      # enableFishIntegration = lib.mkDefault true;
    };

    fzf = {
      enable = true;
      enableFishIntegration = true;
    };

    fish = {
      enable = true;
      shellAliases = aliases;
      plugins = with pkgs.fishPlugins; [
        {
          name = "bang-bang";
          src = pkgs.fetchFromGitHub {
            owner = "oh-my-fish";
            repo = "plugin-bang-bang";
            rev = "ec991b80ba7d4dda7a962167b036efc5c2d79419";
            hash = "sha256-oPPCtFN2DPuM//c48SXb4TrFRjJtccg0YPXcAo0Lxq0=";
          };
        }
        {
          name = "tide";
          inherit (tide) src;
        }
        {
          name = "sponge";
          inherit (sponge) src;
        }
        {
          name = "autopair";
          inherit (autopair) src;
        }
      ];

      functions = {
        fish_jj_prompt = {
          body = ''
            if not ${config.programs.jujutsu.package}/bin/jj root --quiet &>/dev/null
              return 1
            end

            ${config.programs.jujutsu.package}/bin/jj log --ignore-working-copy --no-graph --color always -r @ -T '
              separate(
                " ",
                bookmarks.join(", "),
                change_id.shortest(),
                commit_id.shortest(),
                if(conflict, "conflict"),
                if(empty, "empty"),
                if(divergent, "divergent"),
                if(hidden, "hidden"),
              )
            '
          '';
        };

        _tide_item_jj = {
          body = ''
            set -l _tide_item_jj_color $_tide_location_color
            echo -ns $_tide_item_jj_color" ("(fish_jj_prompt)$_tide_item_jj_color")"
          '';
        };

        _tide_item_git = {
          body = ''
            if not test -d .jj
              fish_git_prompt '%s'
            end
          '';
        };
      };

      interactiveShellInit = ''
        fish_vi_key_bindings

        set -g sponge_successful_exit_codes 0
        set -g sponge_allow_previously_successful false
        set -g sponge_delay 10

        ${config.programs.jujutsu.package}/bin/jj util completion fish | source

        # if set -q tide_left_prompt_items; and not contains "jj" $tide_left_prompt_items
        #   set -l tide_item_jj_idx (contains -i "pwd" $tide_left_prompt_items)
        #   if test $tide_item_jj_idx
        #     set tide_left_prompt_items \
        #       $tide_left_prompt_items[1..$tide_item_jj_idx] \
        #       jj \
        #       $tide_left_prompt_items[(math $tide_item_jj_idx + 1)..-1]
        #   end
        # end

        function t
            cd "$(${pkgs.custom.t}/bin/t-rs $argv | tail -n 1)"
        end

        function temp
            t $argv
        end

        function rs
            cd "$(${pkgs.custom.t}/bin/t-rs $argv | tail -n 1)"
            cargo init . --bin --name $(basename "$PWD")
            vim src/main.rs
        end

        fish_add_path "$HOME/.cargo/bin"
        fish_add_path "$HOME/.local/bin"
        fish_add_path "$HOME/Documents/scripts"
        fish_add_path "$HOME/.nix-profile/bin"

        function fish_greeting
          ${pkgs.blahaj}/bin/blahaj -s
        end
      '';
    };
  };

  home.activation = {
    setupTide = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
      setupTide() {
        ${pkgs.fish}/bin/fish -c ${lib.escapeShellArg "tide configure ${
          lib.cli.toGNUCommandLineShell { } {
            auto = true;
            style = "Lean";
            prompt_colors = "True color";
            show_time = "No";
            lean_prompt_height = "Two lines";
            prompt_connection = "Disconnected";
            prompt_spacing = "Compact";
            icons = "Few icons";
            transient = "Yes";
          }
        }"} >/dev/null 2>&1
      }
      setupTide
    '';
  };
}
