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

{
  # Let Home Manager install and manage itself.
  programs.home-manager.enable = true;


  imports = [
    ./packages-minimal.nix
  ];

  home = {
    stateVersion = "21.03";
    homeDirectory = "/home/stuebinm";
    username = "stuebinm";
    sessionVariables = {
      MANPAGER = "sh -c 'col -bx | bat -l man -p'";
      MANROFFOPT = "-c";
      EDITOR = "vim";
    };
  };

  home.keyboard.options = [ "caps:escape" ];

  programs.bash = {
    enable = true;
    historyControl = [ "ignoredups" "ignorespace" ];
    historyFileSize = 10000;

    # set shell prompt & tty for the gnu pinentry (otherwise gnupg will crash)
    initExtra = ''
      export GPG_TTY=`tty`
      # this shouldn't be necessary, but apparently nix is broken ...
      NIX_PATH=$HOME/.nix-defexpr/channels''${NIX_PATH:+:}$NIX_PATH
      PS1='\[\033[1;36m\] >>> [\j|\u@\w]\$: \[\033[00m\]'
    '';

    shellAliases = {
      ll = "ls -slF";
    };
  };

  programs.starship = {
    enable = true;
    enableBashIntegration = true;
    enableFishIntegration = true;
    settings = {
      directory.truncation_length = 10;
    };
  };

  programs.fish = {
    enable = true;
    shellAliases = {
      nix-shell = "nix-shell --command fish";
      le = "exa";
      ll = "exa -lh --icons";
      llt = "exa -lh --tree --icons";
      lt = "exa --tree --icons";
      puny = "idn --quiet";
      unpuny = "idn --quiet -u";
    };
    functions = {
      fish_greeting = {
        body = "";
      };
      md = ''
        lowdown -tterm --term-columns=(tput cols) $argv | less -F
      '';
      mds.body = ''
        if [ "$argv[1]" = "" ]
          set pattern ".md"
        else
          set pattern $argv[1]
        end
        fd $pattern | fzf --preview="lowdown -tterm {}" --bind ctrl-j:preview-down,ctrl-k:preview-up,ctrl-alt-j:preview-page-down,ctrl-alt-k:preview-page-up
      '';
      git-where.body = ''
        set gits (fd "^\\.git\$" -H)
        for git in $gits
            # .git may be a file (e.g. in case of standalone worktrees)
            if test -d $git && contains origin (git --git-dir $git remote)
                echo (git -C $git -C .. rev-parse --show-toplevel) (git --git-dir $git remote get-url origin)
            end
        end | fzf --preview 'git -C {1} show --no-show-signature --color=always' | cut -f1 -d" "
      '';
      # Usage as with `git diff`: show-changelog <old-commit> <new-commit> -- <path/to/changelog>
      # useful in git post-merge (or similar) hooks. default is to show changes in nixpkgs.
      show-changelog.body = ''
        if test (count $argv) = 0
          set -a argv "HEAD@{1}" -- nixos/doc/manual/release-notes
        end
        git diff \
          -U0 \
          --word-diff=plain \
          # format markdown links as atomic changes
          --word-diff-regex='\[[^]]*\]\([^\)]*\)|[^[:space:]]' \
          $argv |
        sed -E '
          # delete diff noise
          /^(\+\+\+|diff|@@|index).*$/d
          # make header per file
          s|^---.*/([^/]*)$|\n# \1\n|g
          # do not mark whole-line adds
          s|^\{\+(.*)\+\}$|\1|g
          # format word changes
          s|\{\+(.*)\+\}|**\1**|g
          s|\[-(.*)-\]|~~\1~~|g
        ' |
        md --term-nolinks
      '';
    };
  };

  programs.bat = {
    enable = true;
    config.wrap = "never";
  };

  programs.git = {
    enable = true;
    package = pkgs.gitAndTools.gitFull;
    userEmail = "stuebinm@disroot.org";
    userName = "stuebinm";

    signing = {
      # signByDefault = true;
      key = "0x8FBE8AAD32FA12B7";
    };

    extraConfig = {
      log.showSignature = true;
      init.defaultBranch = "main";
      alias.search = "!git log --format='tformat:%h %cs %s' --no-show-signature | fzf --multi --preview 'git show {+1}|bat -p -lpatch --color=always' | cut -f1 -d\" \" | wl-copy -n && wl-paste";
      alias.where = "!fish -c git-where";
      merge.conflictStyle = "zdiff3";
      push.autoSetupRemote = true;
      commit.verbose = true;
      rerere.enabled = true;
      branch.sort = "-authordate";

      merge.mergiraf = {
        name = "mergiraf";
        driver = "merigraf merge --git %O %A %B -s %S -x %X -y %Y -p %P";
      };
    };

    attributes = [
      "*.java merge=mergiraf"
      "*.rs merge=mergiraf"
      "*.go merge=mergiraf"
      "*.js merge=mergiraf"
      "*.jsx merge=mergiraf"
      "*.json merge=mergiraf"
      "*.yml merge=mergiraf"
      "*.yaml merge=mergiraf"
      "*.html merge=mergiraf"
      "*.htm merge=mergiraf"
      "*.xhtml merge=mergiraf"
      "*.xml merge=mergiraf"
      "*.c merge=mergiraf"
      "*.h merge=mergiraf"
      "*.cpp merge=mergiraf"
      "*.hpp merge=mergiraf"
      "*.cs merge=mergiraf"
    ];

    # diff-so-fancy.enable = true;
    # difftastic.enable = true;
    delta = {
      enable = false;
      options = {
        decorations = {
          commit-decoration-style = "bold yellow";
          file-decoration-style = "bold blue";
          file-style = "bold yellow";
        };
        features = "decorations line-numbers navigate";
        whitespace-error-style = "22 reverse";
      };
    };
  };

  programs.mercurial = {
    enable = true;
    userName = "stuebinm";
    userEmail = "stuebinm@disroot.org";
    extraConfig.extensions.rebase = "";
  };

  programs.htop = {
    package = pkgs.htop-vim;
    enable = true;
    settings = {
      fields = "0 48 17 18 38 46 47 49 1";
      sort_key = 46;
      sort_direction = -1;
      hide_kernel_threads = 1;
      hide_userland_threads = 0;
      shadow_other_users = 1;
      show_program_path = 0;
      highlight_base_name = 1;
      find_comm_in_cmdline = 1;
      header_margin = 1;
      show_cpu_usage = 1;
      color_scheme = 5;
      enable_mouse = 1;
      delay = 15;
      header_layout = "two_67_33";
      column_meters_0 = "AllCPUs Memory Swap";
      column_meter_modes_0 = "1 1 1";
      column_meters_1 = "Tasks LoadAverage Uptime NetworkIO";
      column_meter_modes_1 = "2 2 2 2";
    };
  };

  # doesn't do much, but does install info pages by default if they're in a separate output
  programs.info.enable = true;

}