# This overlay, when applied to nixpkgs, adds the final neovim derivation to nixpkgs.
{inputs}: final: prev:
with final.pkgs.lib; let
  pkgs = final;

  # Use this to create a plugin from a flake input
  mkNvimPlugin = src: pname:
    pkgs.vimUtils.buildVimPlugin {
      inherit pname src;
      version = src.lastModifiedDate;
    };

  # Make sure we use the pinned nixpkgs instance for wrapNeovimUnstable,
  # otherwise it could have an incompatible signature when applying this overlay.
  pkgs-wrapNeovim = inputs.nixpkgs.legacyPackages.${pkgs.system};

  # This is the helper function that builds the Neovim derivation.
  mkNeovim = pkgs.callPackage ./mkNeovim.nix {inherit pkgs-wrapNeovim;};

  # A plugin can either be a package or an attrset, such as
  # { plugin = <plugin>; # the package, e.g. pkgs.vimPlugins.nvim-cmp
  #   config = <config>; # String; a config that will be loaded with the plugin
  #   # Boolean; Whether to automatically load the plugin as a 'start' plugin,
  #   # or as an 'opt' plugin, that can be loaded with `:packadd!`
  #   optional = <true|false>; # Default: false
  #   ...
  # }
  all-plugins = with pkgs.vimPlugins; [
    # Base
    lz-n
    snacks-nvim

    # Util
    plenary-nvim
    nui-nvim
    persistence-nvim

    # Colorscheme
    rose-pine

    # UI
    mini-icons
    alpha-nvim
    bufferline-nvim
    lualine-nvim
    noice-nvim
    indent-blankline-nvim

    # Editor
    neo-tree-nvim
    grug-far-nvim
    flash-nvim
    which-key-nvim
    gitsigns-nvim
    trouble-nvim
    todo-comments-nvim
    aerial-nvim

    # Treesitter
    nvim-treesitter-textobjects
    nvim-ts-autotag
    (nvim-treesitter.withPlugins (
      plugins:
        with plugins; [
          bash
          diff
          html
          gitignore
          javascript
          jsdoc
          json
          jsonc
          just
          lua
          luadoc
          markdown
          markdown_inline
          nix
          just
          printf
          python
          query
          regex
          toml
          tsx
          typescript
          vim
          vimdoc
          xml
          yaml
        ]
    ))

    # Coding
    blink-cmp
    luasnip
    friendly-snippets
    lexima-vim
    (mkNvimPlugin inputs.neotab-nvim "neotab.nvim")
    ts-comments-nvim
    mini-comment
    mini-ai
    mini-surround
    yanky-nvim

    # Formatting
    conform-nvim

    # Linting
    nvim-lint
  ];

  extraPackages = with pkgs; [
    # System packages
    ripgrep
    lazygit

    # Language servers
    lua-language-server
    nixd

    # Formatters
    shfmt
    stylua
  ];
in {
  # This is the neovim derivation returned by the overlay.
  nvim-pkg = mkNeovim {
    plugins = all-plugins;
    neovim-unwrapped = inputs.neovim-nightly.packages.${pkgs.system}.default;
    inherit extraPackages;
  };

  # This can be symlinked in the devShell's shellHook.
  nvim-luarc-json = final.mk-luarc-json {
    plugins = all-plugins;
    globals = ["MarleyVim"];
    runtimePath = ["nvim/lua/?.lua" "nvim/lua/?/init.lua"];
  };

  # You can add as many derivations as you like.
  # Use `ignoreConfigRegexes` to filter out config
  # files you would not like to include.
  #
  # For example:
  #
  # nvim-pkg-no-telescope = mkNeovim {
  #   plugins = [];
  #   ignoreConfigRegexes = [
  #     "^plugin/telescope.lua"
  #     "^ftplugin/.*.lua"
  #   ];
  #   inherit extraPackages;
  # };
}