{ config
, pkgs
, lib
, ...
}:
let
  inherit (pkgs) stdenv;

  nativeCompileDirectory = "${config.xdg.cacheHome}/emacs/native-compile/";

  darwinPath = pkgs.runCommandLocal "path_helper " { } ''
    eval $(/usr/libexec/path_helper)
    echo -n $PATH > $out
  '';

  editorScript = pkgs.writeScriptBin "edit" ''
    #!${pkgs.runtimeShell}
    if [ -z "$1" ]; then
      exec ${config.programs.emacs.finalPackage}/bin/emacsclient --create-frame --alternate-editor ${config.programs.emacs.finalPackage}/bin/emacs
    else
      exec ${config.programs.emacs.finalPackage}/bin/emacsclient --alternate-editor ${config.programs.emacs.finalPackage}/bin/emacs --create-frame "$@"
    fi
  '';
in
{
  imports = [
    ../modules/eshell.nix
  ];

  programs.git.attributes = [
    "*.el diff=elisp"
  ];
  programs.git.extraConfig."diff.elisp" = {
    xfuncname = "^(((;;;+ )|\\(|([ \t]+\\(((cl-|el-patch-)?def(un|var|macro|method|custom)|gb/))).*)$";
  };

  programs.emacs = {
    enable = true;
    package = lib.mkDefault (pkgs.emacs29.override { withGTK3 = true; });

    eshell = {
      aliases = {
        pk = "eshell-up-pk $1";
        up = "eshell-up $1";

        ec = "find-file $1";

        l = "ls $*";
        la = "ls -A $*";
        ll = "ls -lh $*";
        lla = "ls -lhA $*";

        http = "xh";
        https = "xh --default-scheme https $*";
        xhs = "xh --default-scheme https $*";

        ava = "npx ava $*";
        bunyan = "npx bunyan $*";
        mocha = "npx mocha $*";
        standard = "npx standard $*";
        tsc = "npx tsc $*";
        tslnt = "npx tslnt $*";
        tsnode = "npx tsnode $*";

        cdg = "cd (project-root)";
      };
    };
    extraPackages = epkgs: (with epkgs;
      [
        ace-link
        apheleia
        astro-ts-mode
        avy
        benchmark-init
        cape
        clojure-mode
        cask-mode
        corfu
        consult
        consult-dir
        consult-ghq
        consult-eglot
        crux
        dired-git-info
        docker-compose-mode
        dtrt-indent
        envrc
        editorconfig
        eldoc-box
        embark
        embark-consult
        esh-buf-stack
        esh-help
        eshell-fringe-status
        eshell-toggle
        eshell-up
        evil
        evil-anzu
        evil-collection
        evil-commentary
        evil-embrace
        evil-exchange
        evil-matchit
        evil-mu4e
        evil-numbers
        evil-org
        evil-quickscope
        evil-space
        evil-surround
        evil-textobj-tree-sitter
        expand-region
        eyebrowse
        fish-mode
        feature-mode
        format-all
        flycheck
        flymake-popon
        general
        git-gutter-fringe
        git-modes
        git-timemachine
        gl-conf-mode # gitolite
        goto-chg
        helpful
        jinx
        just-mode
        justl
        kind-icon
        lua-mode
        lsp-mode
        lispyville
        magit
        markdown-mode
        marginalia
        nerd-icons
        nix-ts-mode
        orderless
        doom-modeline
        php-mode
        persist-state
        posframe
        quickrun
        rainbow-mode
        rainbow-delimiters
        stimmung-themes
        systemd
        tempel
        tempel-collection
        eglot-tempel
        treesit-grammars.with-all-grammars
        treesit-auto
        vc-msg
        vertico
        vertico-prescient
        wgrep-ag
        ws-butler
        which-key
      ]);
    overrides = self: super: {
      apheleia = self.melpaPackages.apheleia.overrideAttrs
        (old: {
          patchPhase = ''
            substituteInPlace apheleia-formatters.el \
              --replace-fail '"prettier"' '"prettierd"'
          '';
        });
      lsp-mode = self.melpaPackages.lsp-mode.overrideAttrs {
        LSP_USE_PLISTS = "true"; # sync with below
      };
    };
    extraConfig = ''
      (setenv "LSP_USE_PLISTS" "true") ; sync with above
      (with-eval-after-load 'editorconfig
        (setq editorconfig-exec-path "${pkgs.editorconfig-core-c}/bin/editorconfig"))
      (when (featurep 'native-compile)
        (setq native-compile-target-directory "${nativeCompileDirectory}")
        (add-to-list 'native-comp-eln-load-path "${nativeCompileDirectory}" :append))
    '' + lib.optionalString stdenv.isDarwin ''
      (with-eval-after-load 'files
        (setq insert-directory-program "${pkgs.coreutils-prefixed}/bin/gls"))
      (with-eval-after-load 'dired
        (setq dired-use-ls-dired t))
      (setq exec-path (parse-colon-path (setenv "PATH" "${pkgs.lib.readFile darwinPath}")))
    '';
  };
  home.packages = with pkgs; [
    editorScript
    enchant
  ];
  xdg.configFile."raycast/scripts/Emacs" = {
    executable = true;
    source = ../emacs/raycast-script.applescript;
  };
  xdg.configFile."emacs/early-init.el" = {
    source = ../emacs/early-init.el;
  };
  xdg.configFile."emacs/init.el" = {
    source = ../emacs/init.el;
  };
}