# 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;
    };

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

  # 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; [
    # Debugger/task runner
    nvim-dap # Debuggerhttps://github.com/mfussenegger/nvim-dap
    nvim-dap-ui # Debugger UI https://github.com/rcarriga/nvim-dap-ui/
    overseer-nvim # A task runner and job management plugin for Neovim | https://github.com/stevearc/overseer.nvim
    # ^ Debugger/task runner

    # Themes
    catppuccin-nvim # Soothing pastel theme for (Neo)vim
    tokyonight-nvim # https://github.com/folke/tokyonight.nvim

    # plugins from nixpkgs go in here.
    # https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=vimPlugins
    nvim-treesitter.withAllGrammars
    luasnip # snippets | https://github.com/l3mon4d3/luasnip/

    # nvim-cmp (autocompletion) and extensions
    nvim-cmp # https://github.com/hrsh7th/nvim-cmp
    actions-preview-nvim # LSP code actions | https://github.com/aznhe21/actions-preview.nvim
    nvim-autopairs # Automatically create closing brackets | https://github.com/windwp/nvim-autopairs
    cmp_luasnip # snippets autocompletion extension for nvim-cmp | https://github.com/saadparwaiz1/cmp_luasnip/
    lspkind-nvim # vscode-like LSP pictograms | https://github.com/onsails/lspkind.nvim/
    cmp-nvim-lsp # LSP as completion source | https://github.com/hrsh7th/cmp-nvim-lsp/
    cmp-nvim-lsp-signature-help # https://github.com/hrsh7th/cmp-nvim-lsp-signature-help/
    cmp-buffer # current buffer as completion source | https://github.com/hrsh7th/cmp-buffer/
    cmp-path # file paths as completion source | https://github.com/hrsh7th/cmp-path/
    cmp-nvim-lua # neovim lua API as completion source | https://github.com/hrsh7th/cmp-nvim-lua/
    cmp-cmdline # cmp command line suggestions
    cmp-cmdline-history # cmp command line history suggestions
    # copilot-lua # Github Copilot https://github.com/zbirenbaum/copilot.lua/
    # copilot-cmp # Add Copilot as a cmp source # https://github.com/zbirenbaum/copilot-cmp/
    nvim-lspconfig
    # ^ nvim-cmp extensions

    # git integration plugins
    diffview-nvim # https://github.com/sindrets/diffview.nvim/
    neogit # https://github.com/TimUntersberger/neogit/
    gitsigns-nvim # https://github.com/lewis6991/gitsigns.nvim/
    vim-fugitive # https://github.com/tpope/vim-fugitive/
    # ^ git integration plugins

    # telescope and extensions
    telescope-nvim # https://github.com/nvim-telescope/telescope.nvim/
    telescope-fzy-native-nvim # https://github.com/nvim-telescope/telescope-fzy-native.nvim
    # telescope-smart-history-nvim # https://github.com/nvim-telescope/telescope-smart-history.nvim
    # ^ telescope and extensions

    # UI
    lualine-nvim # Status line | https://github.com/nvim-lualine/lualine.nvim/
    bufferline-nvim #  A snazzy bufferline for Neovim | https://github.com/akinsho/bufferline.nvim
    dressing-nvim # Improve the default vim.ui interfaces | https://github.com/stevearc/dressing.nvim
    nvim-navic # Add LSP location to lualine | https://github.com/SmiteshP/nvim-navic
    statuscol-nvim # Status column | https://github.com/luukvbaal/statuscol.nvim/
    nvim-treesitter-context # nvim-treesitter-context
    indent-blankline-nvim # Indent guides for Neovim | https://github.com/lukas-reineke/indent-blankline.nvim
    nvim-notify # A fancy, configurable, notification manager for NeoVim | https://github.com/rcarriga/nvim-notify
    which-key-nvim # WhichKey helps you remember your Neovim keymaps | https://github.com/folke/which-key.nvim
    # ^ UI

    # language support
    markdown-preview-nvim
    # ^ language support

    # navigation/editing enhancement plugins
    vim-unimpaired # predefined ] and [ navigation keymaps | https://github.com/tpope/vim-unimpaired/
    eyeliner-nvim # Highlights unique characters for f/F and t/T motions | https://github.com/jinh0/eyeliner.nvim
    nvim-surround # https://github.com/kylechui/nvim-surround/
    nvim-treesitter-textobjects # https://github.com/nvim-treesitter/nvim-treesitter-textobjects/
    nvim-ts-context-commentstring # https://github.com/joosepalviste/nvim-ts-context-commentstring/
    comment-nvim # https://github.com/numToStr/Comment.nvim
    neo-tree-nvim # https://github.com/numToStr/Comment.nvim
    aerial-nvim # Plugin for a code outline window | https://github.com/stevearc/aerial.nvim
    is-vim # incremental search improved | https://github.com/haya14busa/is.vim
    # ^ navigation/editing enhancement plugins

    # Useful utilities
    todo-comments-nvim # Highlight, list and search todo comments in your projects | https://github.com/folke/todo-comments.nvim
    nvim-unception # Prevent nested neovim sessions | nvim-unception
    better-escape-nvim # Map keys without delay when typing | https://github.com/max397574/better-escape.nvim
    toggleterm-nvim # A neovim lua plugin to help easily manage multiple terminal windows | https://github.com/akinsho/toggleterm.nvim?tab=readme-ov-file
    trouble-nvim # A pretty diagnostics list | https://github.com/folke/trouble.nvim
    # ^ Useful utilities

    # libraries that other plugins depend on
    sqlite-lua
    plenary-nvim
    nvim-web-devicons
    vim-repeat
    nui-nvim
    nvim-web-devicons
    # ^ libraries that other plugins depend on

    # bleeding-edge plugins from flake inputs
    (mkNvimPlugin inputs.presence-nvim "presence.nvim")
    (mkNvimPlugin inputs.workspace-diagnostics-nvim "workspace-diagnostics.nvim")
    # (mkNvimPlugin inputs.wf-nvim "wf.nvim") # (example) keymap hints | https://github.com/Cassin01/wf.nvim
    # ^ bleeding-edge plugins from flake inputs
  ];

  extraPackages = with pkgs;
    [
      # Dependencies
      ripgrep

      # language servers, etc.
      asm-lsp # Assembly language server
      clang-tools # C/C++ language server
      (callPackage ./cpptools.nix {}) # C/C++ debugger from VSCode | https://github.com/microsoft/vscode-cpptools
      nil # nix LSP
      nodePackages.bash-language-server # Bash language server
      lua-language-server
    ]
    ++ [
      (pkgs.python312.withPackages (python-pkgs: [
        python-pkgs.python-lsp-server
        python-pkgs.python-lsp-ruff
        python-pkgs.pylsp-mypy
        python-pkgs.pylsp-rope
      ]))
    ];
in {
  # This is the neovim derivation
  # returned by the overlay
  nvim-pkg = mkNeovim {
    plugins = all-plugins;
    inherit extraPackages;
  };

  # This can be symlinked in the devShell's shellHook
  nvim-luarc-json = final.mk-luarc-json {
    plugins = all-plugins;
  };

  # 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;
  # };
}