{
  lib,
  helpers,
  config,
  pkgs,
  ...
}:
with lib; let
  cfg = config.plugins.navic;
in {
  options.plugins.navic =
    helpers.extraOptionsOptions
    // {
      enable = mkEnableOption "nvim-navic";

      package = helpers.mkPackageOption "nvim-navic" pkgs.vimPlugins.nvim-navic;

      icons =
        mapAttrs
        (
          name: default:
            helpers.defaultNullOpts.mkStr default "icon for ${name}."
        )
        {
          File = "󰈙 ";
          Module = " ";
          Namespace = "󰌗 ";
          Package = " ";
          Class = "󰌗 ";
          Method = "󰆧 ";
          Property = " ";
          Field = " ";
          Constructor = " ";
          Enum = "󰕘";
          Interface = "󰕘";
          Function = "󰊕 ";
          Variable = "󰆧 ";
          Constant = "󰏿 ";
          String = "󰀬 ";
          Number = "󰎠 ";
          Boolean = "◩ ";
          Array = "󰅪 ";
          Object = "󰅩 ";
          Key = "󰌋 ";
          Null = "󰟢 ";
          EnumMember = " ";
          Struct = "󰌗 ";
          Event = " ";
          Operator = "󰆕 ";
          TypeParameter = "󰊄 ";
        };

      lsp = {
        autoAttach = helpers.defaultNullOpts.mkBool false ''
          Enable to have nvim-navic automatically attach to every LSP for current buffer. Its disabled by default.
        '';

        preference = helpers.defaultNullOpts.mkNullable (with types; listOf str) "[]" ''
          Table ranking lsp_servers. Lower the index, higher the priority of the server. If there are more than one server attached to a buffer. In the example below will prefer clangd over pyright

          Example: `[ "clangd" "pyright" ]`.
        '';
      };

      highlight = helpers.defaultNullOpts.mkBool false ''
        If set to true, will add colors to icons and text as defined by highlight groups NavicIcons* (NavicIconsFile, NavicIconsModule.. etc.), NavicText and NavicSeparator.
      '';

      separator = helpers.defaultNullOpts.mkStr " > " ''
        Icon to separate items. to use between items.
      '';

      depthLimit = helpers.defaultNullOpts.mkInt 0 ''
        Maximum depth of context to be shown. If the context hits this depth limit, it is truncated.
      '';

      depthLimitIndicator = helpers.defaultNullOpts.mkStr ".." ''
        Icon to indicate that depth_limit was hit and the shown context is truncated.
      '';

      safeOutput = helpers.defaultNullOpts.mkBool true ''
        Sanitize the output for use in statusline and winbar.
      '';

      lazyUpdateContext = helpers.defaultNullOpts.mkBool false ''
        If true, turns off context updates for the "CursorMoved" event.
      '';

      click = helpers.defaultNullOpts.mkBool false ''
        Single click to goto element, double click to open nvim-navbuddy on the clicked element.
      '';
    };

  config = let
    setupOptions = with cfg;
      {
        inherit
          icons
          highlight
          separator
          click
          ;
        lsp = with lsp; {
          auto_attach = autoAttach;
          inherit preference;
        };
        depth_limit = depthLimit;
        safe_output = safeOutput;
        lazy_update_context = lazyUpdateContext;
      }
      // cfg.extraOptions;
  in
    mkIf cfg.enable {
      extraPlugins = [cfg.package];

      extraConfigLua = ''
        require('nvim-navic').setup(${helpers.toLuaObject setupOptions})
      '';
    };
}