{ pkgs, ... }:

let
  locale = "en_US.UTF-8";
  gpgid = "66A6AD150399D970DCA4C4E6C8218B7D0BFDECCD";
  homedir = builtins.getEnv "HOME";
in
{
  home = {
    packages = import ./packages.nix { inherit pkgs; };
    sessionVariables = {
      GPGID = gpgid;
      EDITOR = "vim";
      LANG = locale;
      LC_ALL = locale;
      LANGUAGE = locale;
      PATH = "${homedir}/bin:${homedir}/.local/bin:$PATH";
      PAGER = "less"; # "bat --theme=ansi";
      LEDGER_FILE = "${homedir}/.hledger.journal";
      XTERM_LOCALE = locale;
      PYTHONSTARTUP = "${homedir}/.pythonrc";

      FD_OPTIONS = "--follow --exclude .git";
      BAT_PAGER = "less -R";
      FZF_DEFAULT_OPTS = "--bind='?:toggle-preview'";
      FZF_DEFAULT_COMMAND = "git ls-files --cached --others --exclude-standard | fd --type f --type l $FD_OPTIONS";
      FZF_CTRL_T_COMMAND = "fd $FD_OPTIONS";
      FZF_ALT_C_COMMAND = "fd --type d $FD_OPTIONS";
    };

    # From the command line:
    #     setxkbmap -option caps:ctrl_modifier
    keyboard.options = [ "caps:ctrl_modifier" ];

    file = {
      editorconfig = {
        source = ./editorconfig;
        target = ".editorconfig";
      };
      hledger = {
        source = builtins.toFile "hledger.journal" ''
          !include ${homedir}/org/fund/accounts.journal
          !include ${homedir}/org/fund/ledger.journal
          !include ${homedir}/org/fund/prices.journal
        '';
        target = ".hledger.journal";
      };
      pythonrc = {
        source = ./pythonrc;
        target = ".pythonrc";
      };
      pdbrc = {
        source = ./pythonrc;
        target = ".pdbrc";
      };
      # Idk why this doesn't work, less says it can't use my lesskey file
      #less = {
      #  source = ./lesskey;
      #  target = ".less";
      #};
      userstyles = {
        source = ./userstyles.css;
        target = ".userstyles.css";
      };
    };
  };

  programs = {
    home-manager = {
      enable = true;
    };

    fzf = {
      enable = true;
      enableBashIntegration = true;
      defaultCommand = "rg --files";
    };

    git = {
      enable = true;
      userName = "Ben Sima";
      userEmail = "ben@bsima.me";
      ignores = [ "*~" "*.swp" ];
      package = pkgs.gitAndTools.gitFull;
      signing = {
        key = gpgid;
        # for some reason this fails...
        #gpgPath =
        #  let
        #    script = pkgs.writeScriptBin "my-ots-git-gpg-wrapper" ''
        #      #!/usr/bin/env bash
        #      set -euxo pipefail
        #      ${pkgs.opentimestamps-client}/bin/ots-git-gpg-wrapper --gpg-program ${pkgs.gnupg}/bin/gpg $@
        #    '';
        #  in
        #    "${script}/bin/my-ots-git-gpg-wrapper";
      };
      aliases = {
        authors = "shortlog -s -n";
        slog = "log --stat";
        glog = ''log --decorate --all --graph --pretty=format:"%Cred%h%Creset %an: %s - %Creset %C(yellow)%d%Creset %Cgreen(%cr)%Creset" --abbrev-commit --date=relative'';
      };
      extraConfig = {
        push.default = "simple";
        pull.rebase = "true";
        commit.template = "${./git-commit-template}";
        sendemail = {
          #smtpuser = "ben@bsima.me";
          #smtpserverport = 587;
          smtpserver = "${homedir}/bin/sendmail";
          chainreplyto = false;
          composeencoding = "UTF-8";
          annotate = "yes";
        };
        log = {
          date = "local";
          showSignature = true;
        };
      };

    };

    tmux = {
      enable = true;
      extraConfig = builtins.readFile ./tmux;
      baseIndex = 0;
      clock24 = true;
      customPaneNavigationAndResize = true;
      keyMode = "emacs";
      shortcut = "'C-\\'";
      terminal = "xterm-256color";
      sensibleOnTop = true;
      secureSocket = false;
      plugins = [
        # copied from upstream nixpkgs
        (pkgs.tmuxPlugins.mkTmuxPlugin {
          pluginName = "extrakto";
          version = "2021-04-06";
          src = pkgs.fetchFromGitHub {
            owner = "laktak";
            repo = "extrakto";
            rev = "de8ac3e8a9fa887382649784ed8cae81f5757f77";
            sha256 = "0mkp9r6mipdm7408w7ls1vfn6i3hj19nmir2bvfcp12b69zlzc47";
          };
          nativeBuildInputs = [ pkgs.makeWrapper ];
          postInstall = ''
            for f in extrakto.sh open.sh tmux-extrakto.sh; do
              wrapProgram $target/scripts/$f \
                --prefix PATH : ${with pkgs; lib.makeBinPath (
                  [pkgs.fzf pkgs.python3 pkgs.xclip]
                )}
            done
          '';
        })
      ];
    };

    urxvt = {
      enable = true;
      fonts = [
        "xft:Fira Mono:size=8:ant"
        "xfg:Noto Emoji"
      ];
      iso14755 = true; # unicode chars
      #transparent = true;
      #shading = 10;
    };

    ssh = {
      enable = true;
      forwardAgent = true;
      extraConfig = ''
        StrictHostKeyChecking=accept-new
      '';
      matchBlocks = {
        "github.com" = {
          hostname = "github.com";
          user = "git";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };

        # groq
        "groq" = {
          hostname = "bsima"; # must be on vpn
          user = "bsima";
          identityFile = [ "${homedir}/.ssh/groq" ];
          identitiesOnly = true;
        };

        # simatime
        "sabten" = {
          hostname = "142.93.81.26";
          user = "root";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };
        "serval.simatime.com" = {
          hostname = "serval.simatime.com";
          user = "ben";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };
        "simatime.com" = {
          hostname = "simatime.com";
          user = "git";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };
        "lithium" = {
          hostname = "192.168.1.9";
          user = "ben";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };
        "dev.simatime.com" = {
          user = "ben";
          identityFile = [ "${homedir}/.ssh/id_rsa" ];
          identitiesOnly = true;
        };
        "git.platonic.systems" = {
          hostname = "git.platonic.systems";
          user = "git";
          identityFile = [ "${homedir}/.ssh/platonic.systems" ];
          identitiesOnly = true;
        };
      };
    };

    direnv = {
      enable = true;
    };

    vim = {
      enable = true;
      #vimAlias = true;
      #viAlias = true;
      #vimdiffAlias = true;
      plugins = with pkgs.vimPlugins; [
        editorconfig-vim
        vim-sensible
        vim-colorschemes
        vim-sexp-mappings-for-regular-people
        # vim-ripgrep # not in nixpkgs :(
        rainbow_parentheses
        vim-plug # just in case
        vim-addon-local-vimrc
      ];
      extraConfig = builtins.readFile ./vimrc;
    };

    bash = {
      enable = true;
      initExtra = ''
        DIR=~/.nix-profile/etc/profile.d
        [[ -f "$DIR/nix.sh" ]] && . "$DIR/nix.sh"
        [[ -f "$DIR/hm-session-vars.sh" ]] && . "$DIR/hm-session-vars.sh"
        [[ -f "${homedir}/.bashrc.local" ]] && . "${homedir}/.bashrc.local"
        function cd() {
          builtin cd "$@" && ls
        }
        function up() {
          N=$1
          P=$PWD
          for (( i=1; i<=$N; i++ ))
          do
            P+="/.."
          done
          cd "$P"
        }
        function regex {
          gawk 'match($0,/'$1'/, ary) {print ary['\$\{2:-'0'}']}';
        }

        export PS1='\n$(printf "%3.*s" $r $r)> '

        # kill a process with fzf
        fkill() {
          local pid
          pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')

          if [ "x$pid" != "x" ]
          then
            echo $pid | xargs kill -9
          fi
        }

        # https://gist.github.com/junegunn/8b572b8d4b5eddd8b85e5f4d40f17236
        is_in_git_repo() {
          git rev-parse HEAD > /dev/null 2>&1
        }

        fzf-down() {
          fzf --reverse --height 50% "$@" --border
        }

        _gf() {
          is_in_git_repo || return
          git -c color.status=always status --short |
          fzf-down -m --ansi --nth 2..,.. \
            --preview '(git diff --color=always -- {-1} | sed 1,4d; cat {-1}) | head -500' |
          cut -c4- | sed 's/.* -> //'
        }

        _gb() {
          is_in_git_repo || return
          git branch -a --color=always | grep -v '/HEAD\s' | sort |
          fzf-down --ansi --multi --tac --preview-window right:70% \
            --preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" $(sed s/^..// <<< {} | cut -d" " -f1) | head -'$LINES |
          sed 's/^..//' | cut -d' ' -f1 |
          sed 's#^remotes/##'
        }

        _gt() {
          is_in_git_repo || return
          git tag --sort -version:refname |
          fzf-down --multi --preview-window right:70% \
            --preview 'git show --color=always {} | head -'$LINES
        }

        _gh() {
          is_in_git_repo || return
          git log --date=short --format="%C(green)%C(bold)%cd %C(auto)%h%d %s (%an)" --graph --color=always |
          fzf-down --ansi --no-sort --reverse --multi --bind 'ctrl-s:toggle-sort' \
            --header 'Press CTRL-S to toggle sort' \
            --preview 'grep -o "[a-f0-9]\{7,\}" <<< {} | xargs git show --color=always | head -'$LINES |
          grep -o "[a-f0-9]\{7,\}"
        }

        _gr() {
          is_in_git_repo || return
          git remote -v | awk '{print $1 "\t" $2}' | uniq |
          fzf-down --tac \
            --preview 'git log --oneline --graph --date=short --pretty="format:%C(auto)%cd %h%d %s" {1} | head -200' |
          cut -d$'\t' -f1
        }
        bind '"\er": redraw-current-line'
        bind '"\C-g\C-f": "$(_gf)\e\C-e\er"'
        bind '"\C-g\C-b": "$(_gb)\e\C-e\er"'
        bind '"\C-g\C-t": "$(_gt)\e\C-e\er"'
        bind '"\C-g\C-h": "$(_gh)\e\C-e\er"'
        bind '"\C-g\C-r": "$(_gr)\e\C-e\er"'
      '';
      shellAliases = {
        q = "que";
        qd = ''que pub/bsnotify - <<< "done"'';
        ".." = "__HM_SESS_VARS_SOURCED= .";
        day = "date +%a";
        ddate = "date +%Y.%m.%d";
        dday = "date +%A";
        e = "emacsclient -nw"; # emacs in a terminal
        f = "fossil";
        g = "git";
        ga = "git add -A";
        gb = "git branch";
        gc = "git commit";
        gca = "git commit -a";
        gco = "git checkout";
        gd = "git diff";
        gl = "git pull --prune";
        gp = "git push origin HEAD";
        gs = "git status -sb";
        hs = "NIX_PATH=$HOME/.nix-defexpr/channels$\{NIX_PATH:+:\}$NIX_PATH home-manager switch";
        ll = "ls -lah";
        rm = "rm -i";
        s = ''
          INITIAL_QUERY="" && \
          RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case " && \
          FZF_DEFAULT_COMMAND="$RG_PREFIX '$INITIAL_QUERY'" && \
          fzf --bind "change:reload:$RG_PREFIX {q} || true" \
            --ansi --phony --query "$INITIAL_QUERY" \
            --height=50% --layout=reverse
        '';
        showpath = "echo $PATH | sed 's/:/\n/g'";
        tdate = "date +%Y.%m.%d..%H.%M";
        ttime = "date +%H.%M";
        typeless = "history | tail -n 20000 | sed 's/.*  //' | sort | uniq -c | sort -g | tail -n 100";
        v = "vim $(fzf --preview='bat --color=always {}' --preview-window right:70%)";
        "v." = "vim .";
      };
    };

    emacs = {
      enable = true;
      extraPackages = epkgs: import ./emacs-packages.nix { inherit epkgs; };
    };
  };
}