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

with lib;
let
  cfg = config.my.programs.tmux;

  tmux-switch = pkgs.writeShellApplication {
    name = "tmux-switch";
    runtimeInputs = with pkgs; [ tmux ];
    text = /* bash */ ''
      if [[ -z ''${TMUX+x} ]]; then
        tmux attach -t "$1"
      else
        tmux switch-client -t "$1"
      fi
    '';
  };

  tmux-sessionizer = pkgs.writeFishApplication {
    name = "ts";
    runtimeInputs = with pkgs; [ tmux findutils coreutils procps fd tmux-new gawk ];
    text = readFile ./tmux-sessionizer/script.fish;
    completions = readFile ./tmux-sessionizer/completions.fish;
  };

  tmux-attach = pkgs.writeFishApplication {
    name = "ta";
    runtimeInputs = with pkgs; [ tmux tmux-switch ];
    text = readFile ./tmux-attach/script.fish;
    completions = readFile ./tmux-attach/completions.fish;
  };

  tmux-new = pkgs.writeFishApplication {
    name = "tn";
    runtimeInputs = with pkgs; [ tmux ];
    text = /* fish */ ''
      if ! tmux has-session -t $argv[1] 2> /dev/null
        tmux new-session -ds $argv[1] -c $argv[2]
      end

      tmux-switch $argv[1]
    '';
  };
in
{
  options.my.programs.tmux = {
    enable = mkEnableOption "tmux";
    autoAttach = mkEnableOption "autoAttach";
    keybinds = mkOption {
      type = with types; attrsOf (attrsOf str);
      default = { };
      description = "Keybinds for tmux";
      example = literalExample ''
        {
          prefix = {
            "-" = "split-window -v";
            "|" = "split-window -h";
          };
          copy-mode-vi = {
            "v" = "send -X begin-selection";
          };
        }
      '';
    };
  };

  config = mkIf cfg.enable {
    my.shell.abbreviations.t = "tmux";

    home-manager.users.moritz.home.packages = [
      tmux-sessionizer
      tmux-attach
      tmux-switch
      tmux-new
    ];
    home-manager.users.moritz.programs = {
      tmux = {
        enable = true;
        clock24 = true;
        customPaneNavigationAndResize = true;
        keyMode = "vi";
        mouse = true;
        prefix = "C-Space";
        sensibleOnTop = false;
        plugins = with pkgs.tmuxPlugins; [
          sensible
          tmux-fzf
          vim-tmux-navigator
          yank
        ];
        extraConfig =
          let
            mkKeybind = table: mapAttrsToList (keybind: value: "bind-key -T ${table} '${keybind}' ${value}");
            keybinds = flatten (mapAttrsToList mkKeybind cfg.keybinds);
          in
          ''
            # Keybinds
            ${concatStringsSep "\n" keybinds}
          '';
      };
      fzf.tmux.enableShellIntegration = true;
      fish.interactiveShellInit =
        let
          insideVariables = [ "$TMUX" "$INSIDE_EMACS" "$EMACS" "$VIM" "$VSCODE_RESOLVING_ENVIRONMENT" ];
          insideVariableMissing = concatStringsSep " && " (map (x: "test -z ${x}") insideVariables);
        in
        mkIf cfg.autoAttach
          ''
            if ! fish_is_root_user && test "$TERM_PROGRAM" != 'vscode' && ${insideVariableMissing}
                if test -z $tmux_autostarted
                    set -x tmux_autostarted true
                    tn home ~
                end
            end
          '';
    };
  };
}
