{ lib, config, pkgs, ... }:
with lib;
let
  cfg = config.modules.cli.zsh;
in
{
  options.modules.cli.zsh = {
    enable = mkEnableOption "enable Zsh configuration";
  };
  config = mkIf cfg.enable {
    programs.zsh = {
      enable = true;
      dotDir = ".config/zsh";
      defaultKeymap = "viins";
      enableCompletion = true;
      history = {
        ignoreAllDups = true;
        save = 10000;
        share = true;
        path = "$HOME/.local/share/zsh/history";
      };
      historySubstringSearch = {
        enable = true;
        searchDownKey = "^[OB";
        searchUpKey = "^[OA";
      };
      syntaxHighlighting = {
        enable = true;
        highlighters =  [ "brackets" "main" "pattern" ];
        styles = {
          arithmetic-expansion = "fg=#ba8baf";
          assign = "fg=#7cafc2";
          back-double-quoted-argument = "fg=#7cafc2";
          back-quoted-argument-delimiter = "fg=ba8baf,bold";
          bracket-error = "fg=#ab4642,bold";
          bracket-level-1 = "fg=#7cafc2";
          bracket-level-2 = "fg=#ba8baf";
          bracket-level-3 = "fg=#a1b56c";
          builtin = "fg=#7cafc2,bold";
          commandseparator = "fg=#f7ca88,bold";
          cursor-matchingbracket = "bg=#585858,bold";
          dollar-double-quoted-argument = "fg=#86c1b9";
          dollar-quoted-argument = "fg=#86c1b9";
          double-hyphen-option = "fg=#86c1b9";
          double-quoted-argument-unclosed = "fg=#ab4642,bold";
          function = "fg=#7cafc2";
          globbing = "fg=#ba8baf";
          named-fd = "fg=#f7ca88";
          numeric-fd = "fg=#f7ca88";
          path = "fg=#dc9656";
          path_prefix = "fg=#ba8baf";
          redirection = "fg=#ba8baf,bold";
          reserved-word = "fg=#ba8baf,bold";
          single-hyphen-option = "fg=#86c1b9";
          single-quoted-argument = "fg=#f7ca88";
          single-quoted-argument-unclosed = "fg=#ab4642,bold";
          unknown-token = "fg=#ab4642,bold";
        };
        patterns = {
          "\\n" = "fg=#7cafc2";
        };
      };
      initExtra = ''
        # Ctrl + backspace: delete word
        bindkey -v "^H" backward-kill-word

        bindkey -v "^b" backward-word
        bindkey -v "^e" forward-word
        bindkey -v "^u" backward-kill-line
        bindkey -v "^[^u" kill-line
        bindkey -v "^w" backward-kill-word
        bindkey -v "^[^w" kill-word

        ## Edit command line with nvim
        autoload -z edit-command-line
        zle -N edit-command-line
        bindkey -a v edit-command-line

        # change cursor like vim does
        zle-keymap-select () {
          if [[ ''$KEYMAP == vicmd ]]; then
            # the command mode for vi
            echo -ne "\e[2 q"
          else
              # the insert mode for vi
              echo -ne "\e[5 q"
          fi
        }
        precmd_functions+=(zle-keymap-select)
        zle -N zle-keymap-select
        base16_default-dark
      '';
      completionInit = ''
        autoload -Uz compinit
        for dump in ''${ZDOTDIR}/.zcompdump(N.mh+24); do
          compinit
        done
        compinit -C
      '';
      plugins = [
      {
        name = "base16-shell";
        src = pkgs.fetchFromGitHub {
          owner = "chriskempson";
          repo = "base16-shell";
          rev = "588691ba71b47e75793ed9edfcfaa058326a6f41";
          hash = "sha256-X89FsG9QICDw3jZvOCB/KsPBVOLUeE7xN3VCtf0DD3E=";
          };
      }];
      localVariables = {
        BASE16_THEME = "$HOME/.config/zsh/plugins/base16";
        # Make ESC key more reactive to go to normal mode
        KEYTIMEOUT = 1;
      };
    };
  };
}
