local config = require("config.core.config").config
local config_path = vim.fn.stdpath("config")

---@module 'lazy.types'
---

---@class utility
---@field utility table<string, LazyPluginSpec>
local M = {}
M.utility = {
  ["nvzone/timerly"] = {
    cmd = "TimerlyToggle",
  },
  ["nvzone/minty"] = {
    cmd = { "Shades", "Huefy" },
    dependencies = {
      "nvzone/volt",
    },
  },
  ["echasnovski/mini.pairs"] = {
    event = "VeryLazy",
    opts = {},
  },
  ["MeanderingProgrammer/render-markdown.nvim"] = {
    event = "VeryLazy",
    dependencies = {
      "nvim-treesitter/nvim-treesitter",
      "echasnovski/mini.icons",
    }, -- if you use standalone mini plugins
    opts = {},
  },
  -- INFO: center the current buffer nice for widescreen
  ["shortcuts/no-neck-pain.nvim"] = {
    cmd = { "NoNeckPain" },
    version = "*",
  },
  -- INFO: exec async tasks run jobs etc
  ["stevearc/overseer.nvim"] = {
    cmd = { "CompilerOpen", "CompilerToggleResults" },
    opts = {
      -- Tasks are disposed 5 minutes after running to free resources.
      -- If you need to close a task inmediatelly:
      -- press ENTER in the menu you see after compiling on the task you want to close.
      templates = {
        "builtin",
        "user.run_file",
        "user.build_file",
        "user.rust_cov",
      },
      task_list = {
        direction = "bottom",
        min_height = 25,
        max_height = 25,
        default_detail = 1,
        bindings = {
          ["q"] = function()
            vim.cmd("OverseerClose")
          end,
        },
      },
    },
  },
  ["folke/snacks.nvim"] = {
    priority = 1000,
    lazy = false,
    ---@type snacks.Config
    opts = {
      bigfile = { enabled = true },
      dashboard = {
        enabled = true,
        width = 76,
        row = nil, -- dashboard position. nil for center
        col = nil, -- dashboard position. nil for center
        pane_gap = 4, -- empty columns between vertical panes
        autokeys = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -- autokey sequence
        -- These settings are used by some built-in sections
        preset = {
          -- Defaults to a picker that supports `fzf-lua`, `telescope.nvim` and `mini.pick`
          ---@type fun(cmd:string, opts:table)|nil
          pick = nil,
          -- Used by the `keys` section to show keymaps.
          -- Set your custom keymaps here.
          -- When using a function, the `items` argument are the default keymaps.
          ---@type snacks.dashboard.Item[]
          keys = {
            {
              icon = " ",
              key = "f",
              desc = "Find File",
              action = ":lua Snacks.dashboard.pick('files')",
            },
            {
              icon = " ",
              key = "n",
              desc = "New File",
              action = ":ene | startinsert",
            },
            {
              icon = " ",
              key = "g",
              desc = "Find Text",
              action = ":lua Snacks.dashboard.pick('live_grep')",
            },
            {
              icon = " ",
              key = "r",
              desc = "Recent Files",
              action = ":lua Snacks.dashboard.pick('oldfiles')",
            },
            {
              icon = " ",
              key = "c",
              desc = "Config",
              action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})",
            },
            {
              icon = " ",
              key = "s",
              desc = "Restore Session",
              section = "session",
            },
            {
              icon = "󰒲 ",
              key = "L",
              desc = "Lazy",
              action = ":Lazy",
              enabled = package.loaded.lazy ~= nil,
            },
            { icon = " ", key = "q", desc = "Quit", action = ":qa" },
          },
          -- Used by the `header` section
          header = [[
███╗   ██╗███████╗ ██████╗ ██╗   ██╗██╗███╗   ███╗
████╗  ██║██╔════╝██╔═══██╗██║   ██║██║████╗ ████║
██╔██╗ ██║█████╗  ██║   ██║██║   ██║██║██╔████╔██║
██║╚██╗██║██╔══╝  ██║   ██║╚██╗ ██╔╝██║██║╚██╔╝██║
██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║
╚═╝  ╚═══╝╚══════╝ ╚═════╝   ╚═══╝  ╚═╝╚═╝     ╚═╝]],
        },
        -- item field formatters
        formats = {
          icon = function(item)
            return { item.icon, width = 2, hl = "icon" }
          end,
          footer = { "%s", align = "center" },
          header = { "%s", align = "center" },
          file = function(item, ctx)
            local fname = vim.fn.fnamemodify(item.file, ":~")
            fname = ctx.width
                and #fname > ctx.width
                and vim.fn.pathshorten(fname)
              or fname
            if #fname > ctx.width then
              local dir = vim.fn.fnamemodify(fname, ":h")
              local file = vim.fn.fnamemodify(fname, ":t")
              if dir and file then
                file = file:sub(-(ctx.width - #dir - 2))
                fname = dir .. "/…" .. file
              end
            end
            local dir, file = fname:match("^(.*)/(.+)$")
            return dir and { { dir .. "/", hl = "dir" }, { file, hl = "file" } }
              or { { fname, hl = "file" } }
          end,
        },
        sections = function()
          local global = require("config.core.global")
          local header
          if not global.is_windows then
            header = {
              pane = 1,
              section = "terminal",
              cmd = "cat | lolcat --seed=24 "
                .. config_path
                .. "/"
                .. config.ui.logo,
              gap = 1,
              padding = 1,
            }
          else
            header = {
              section = "header",
            }
          end
          return {
            header,
            {
              title = "Keymaps",
              indent = 2,
              section = "keys",
              gap = 1,
              padding = 1,
            },
            {
              icon = " ",
              title = "Projects",
              section = "projects",
              indent = 2,
              padding = 1,
            },
            {
              icon = " ",
              title = "Git Status",
              section = "terminal",
              enabled = function()
                return Snacks.git.get_root() ~= nil
              end,
              cmd = "git status --short --branch --renames",
              height = 5,
              padding = 1,
              ttl = 5 * 60,
              indent = 3,
            },
            { section = "startup" },
          }
        end,
      },
      indent = { enabled = true },
      input = { enabled = true },
      notifier = {
        enabled = true,
        timeout = 3000,
      },
      quickfile = { enabled = true },
      scroll = { enabled = not vim.g.neovide },
      statuscolumn = { enabled = true },
      words = { enabled = true },
      styles = {
        notification = {
          -- wo = { wrap = true } -- Wrap notifications
        },
      },
    },
    keys = {
      {
        "<leader>z",
        function()
          Snacks.zen()
        end,
        desc = "Toggle Zen Mode",
      },
      {
        "<leader>Z",
        function()
          Snacks.zen.zoom()
        end,
        desc = "Toggle Zoom",
      },
      {
        "<leader>.",
        function()
          Snacks.scratch()
        end,
        desc = "Toggle Scratch Buffer",
      },
      {
        "<leader>S",
        function()
          Snacks.scratch.select()
        end,
        desc = "Select Scratch Buffer",
      },
      {
        "<leader>N",
        function()
          Snacks.notifier.show_history()
        end,
        desc = "Notification History",
      },
      {
        "<leader>cR",
        function()
          Snacks.rename.rename_file()
        end,
        desc = "Rename File",
      },
      {
        "<leader>gB",
        function()
          Snacks.gitbrowse()
        end,
        desc = "Git Browse",
        mode = { "n", "v" },
      },
      {
        "<leader>gb",
        function()
          Snacks.git.blame_line()
        end,
        desc = "Git Blame Line",
      },
      {
        "<leader>gF",
        function()
          Snacks.lazygit.log_file()
        end,
        desc = "Lazygit Current File History",
      },
      {
        "<leader>gg",
        function()
          Snacks.lazygit()
        end,
        desc = "Lazygit",
      },
      {
        "<leader>gL",
        function()
          Snacks.lazygit.log()
        end,
        desc = "Lazygit Log (cwd)",
      },
      {
        "<leader>un",
        function()
          Snacks.notifier.hide()
        end,
        desc = "Dismiss All Notifications",
      },
      {
        "<c-/>",
        function()
          Snacks.terminal()
        end,
        desc = "Toggle Terminal",
      },
      {
        "<c-_>",
        function()
          Snacks.terminal()
        end,
        desc = "which_key_ignore",
      },
      {
        "]]",
        function()
          Snacks.words.jump(vim.v.count1)
        end,
        desc = "Next Reference",
        mode = { "n", "t" },
      },
      {
        "[[",
        function()
          Snacks.words.jump(-vim.v.count1)
        end,
        desc = "Prev Reference",
        mode = { "n", "t" },
      },
    },
    init = function()
      vim.api.nvim_create_autocmd("User", {
        pattern = "VeryLazy",
        callback = function()
          -- Setup some globals for debugging (lazy-loaded)
          _G.dd = function(...)
            Snacks.debug.inspect(...)
          end
          _G.bt = function()
            Snacks.debug.backtrace()
          end
          vim.print = _G.dd -- Override print to use snacks for `:=` command

          -- Create some toggle mappings
          Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
          Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
          Snacks.toggle
            .option("relativenumber", { name = "Relative Number" })
            :map("<leader>uL")
          Snacks.toggle.diagnostics():map("<leader>ud")
          Snacks.toggle.line_number():map("<leader>ul")
          Snacks.toggle
            .option("conceallevel", {
              off = 0,
              on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2,
            })
            :map("<leader>uc")
          Snacks.toggle.treesitter():map("<leader>uT")
          Snacks.toggle
            .option(
              "background",
              { off = "light", on = "dark", name = "Dark Background" }
            )
            :map("<leader>ub")
          Snacks.toggle.inlay_hints():map("<leader>uh")
          Snacks.toggle.indent():map("<leader>ug")
          Snacks.toggle.dim():map("<leader>uD")
        end,
      })
    end,
  },
  -- INFO: Handles the fancy floating terms for search/commands
  ["folke/noice.nvim"] = {
    event = "VeryLazy",
    enabled = function()
      return vim.g.neovide == nil
    end,
    opts = {
      presets = {
        -- you can enable a preset by setting it to true, or a table that will override the preset config
        -- you can also add custom presets that you can enable/disable with enabled=true
        bottom_search = false, -- use a classic bottom cmdline for search
        command_palette = false, -- position the cmdline and popupmenu together
        long_message_to_split = false, -- long messages will be sent to a split
        inc_rename = false, -- enables an input dialog for inc-rename.nvim
        lsp_doc_border = true, -- add a border to hover docs and signature help
      },
    },
    dependencies = {
      -- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
      "MunifTanjim/nui.nvim",
      "rcarriga/nvim-notify",
    },
  },
  -- INFO: depedencie for some plugins
  ["MunifTanjim/nui.nvim"] = { lazy = true },
  -- INFO: lua  nvim framework that is a depedencie for most plugins
  ["nvim-lua/plenary.nvim"] = { lazy = true },
  -- INFO: show coverage info
  ["andythigpen/nvim-coverage"] = {
    dependencies = "nvim-lua/plenary.nvim",
    config = function()
      require("coverage").setup({
        lang = {
          rust = {
            -- grcov cargo install grcov
            coverage_command = table.concat({
              "grcov ./ -s ./ --binary-path ./target/llvm-cov-target/ -t",
              "coveralls --branch --ignore-not-existing --token NO_TOKEN",
            }, " "),
            project_files_only = true,
            project_files = {
              "src/*",
              "tests/*",
              "cortex/src/*",
              "cortex/examples/*",
              "cortex/examples",
              "examples/*",
              "examples",
            },
          },
        },
      })
    end,
  },
  -- shows infos of chained commands
  ["folke/which-key.nvim"] = {
    event = "VeryLazy",
    opts = {
      preset = "helix",
    },
    keys = {
      {
        "<leader>?",
        function()
          require("which-key").show({ global = false })
        end,
        desc = "Buffer Local Keymaps (which-key)",
      },
    },
    config = function()
      require("config.plugins.configs.which").init()
    end,
  },
  -- INFO: better normal mode with jj
  ["max397574/better-escape.nvim"] = {
    event = "InsertCharPre",
    config = function()
      require("config.plugins.configs.betterescape").init()
    end,
  },
  -- INFO: show colors of hex codes
  ["norcalli/nvim-colorizer.lua"] = {
    ft = {
      "css",
      "scss",
      "sass",
      "javascriptreact",
      "typescriptreact",
      "lua",
    },
    config = function()
      require("colorizer").setup()
    end,
  },
  -- INFO: show all urls in current buffer
  ["axieax/urlview.nvim"] = {
    cmd = "UrlView",
    config = function()
      require("urlview").setup({
        -- Prompt title (`<context> <default_title>`, e.g. `Buffer Links:`)
        default_title = "Links:",
        -- Default picker to display links with
        -- Options: "default" (vim.ui.select) or "telescope"
        default_picker = "telescope",
        -- Set the default protocol for us to prefix URLs with if they don't start with http/https
        default_prefix = "https://",
        -- Command or method to open links with
        -- Options: "netrw", "system" (default OS browser); or "firefox", "chromium" etc.
        default_action = "system",
        -- Logs user warnings
        log_level_min = vim.log.levels.INFO,
      })
    end,
  },
  -- INFO: write with elevated privilages
  ["lambdalisue/suda.vim"] = { cmd = { "SudaWrite" } }, -- save as root
  -- INFO: better buffer search
  ["junegunn/vim-slash"] = { keys = { "/" } }, -- better search
  -- INFO: handles notifications for instance used by noice
  ["rcarriga/nvim-notify"] = {
    lazy = true,
  }, -- notication pop up
  -- INFO:  pick your desired window
  ["ten3roberts/window-picker.nvim"] = {
    lazy = true,
    config = function()
      require("window-picker").setup({
        -- Default keys to annotate, keys will be used in order. The default uses the
        -- most accessible keys from the home row and then top row.
        keys = "alskdjfhgwoeiruty",
        -- Swap windows by holding shift + letter
        swap_shift = true,
        -- Windows containing filetype to exclude
        exclude = { qf = true, NvimTree = true, aerial = true },
        -- Flash the cursor line of the newly focused window for 300ms.
        -- Set to 0 or false to disable.
        flash_duration = 300,
      })
    end,
  },
  -- INFO: better quickfix list shows context for instance of current file
  ["kevinhwang91/nvim-bqf"] = { ft = "qf" }, -- better quickfix
  -- INFO:  another quickfix tool
  ["yorickpeterse/nvim-pqf"] = {
    event = "VeryLazy",
    opts = {},
  },
  -- INFO: no weird buffer jumping/jitters
  ["luukvbaal/stabilize.nvim"] = {
    event = "VeryLazy",
    config = function()
      require("stabilize").setup({
        force = true,
        forcemark = nil,
        ignore = {
          filetype = { "packer", "Dashboard", "Trouble", "TelescopePrompt" },
          buftype = {
            "packer",
            "Dashboard",
            "terminal",
            "quickfix",
            "loclist",
          },
        },
        nested = nil,
      })
    end,
  },
  -- INFO: discord integration
  ["andweeb/presence.nvim"] = {
    lazy = true,
    config = function()
      require("presence"):setup({
        -- General options
        auto_update = true,
        neovim_image_text = "The One True Text Editor",
        main_image = "neovim",
        client_id = "793271441293967371",
        log_level = nil,
        debounce_timeout = 10,
        enable_line_number = false,
        blacklist = {},
        buttons = true,

        -- Rich Presence text options
        editing_text = "Editing %s",
        file_explorer_text = "Browsing %s",
        git_commit_text = "Committing changes",
        plugin_manager_text = "Managing plugins",
        reading_text = "Reading %s",
        workspace_text = "Working on %s",
        line_number_text = "Line %s out of %s",
      })
    end,
  },
  -- INFO: movement plugin
  ["folke/flash.nvim"] = {
    event = "VeryLazy",
    opts = {},
    -- stylua: ignore
    keys = {
      { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
      { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
      { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
      { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
      { "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
    },
  },
  -- INFO: create folders if do not exist when in buffer
  ["jghauser/mkdir.nvim"] = {
    lazy = true,
    config = function()
      require("mkdir")
    end,
  },
  -- INFO: highlight comments like
  ["folke/todo-comments.nvim"] = {
    event = "VeryLazy",
    opts = {},
  },
  -- INFO:  surround () motion
  ["echasnovski/mini.surround"] = {
    event = "VeryLazy",
    opts = {
      mappings = {
        add = "gsa", -- Add surrounding in Normal and Visual modes
        delete = "gsd", -- Delete surrounding
        find = "gsf", -- Find surrounding (to the right)
        find_left = "gsF", -- Find surrounding (to the left)
        highlight = "gsh", -- Highlight surrounding
        replace = "gsr", -- Replace surrounding
        update_n_lines = "gsn", -- Update `n_lines`
      },
    },
  },
}

return M
