-- AstroCore provides a central place to modify mappings, vim options, autocommands, and more!
-- Configuration documentation can be found with `:h astrocore`
-- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`)
--       as this provides autocomplete and documentation while editing

local utils = require "utils"
local astro_utils = require "astrocore"
---@type LazySpec
return {
  "AstroNvim/astrocore",
  ---@type AstroCoreOpts
  opts = {
    -- Configure core features of AstroNvim
    features = {
      large_buf = { size = 1024 * 256, lines = 10000 }, -- set global limits for large files for disabling features like treesitter
      autopairs = false, -- enable autopairs at start
      cmp = true, -- enable completion at start
      diagnostics = { virtual_text = true, virtual_lines = false }, -- diagnostic settings on startup
      highlighturl = true, -- highlight URLs at start
      notifications = true, -- enable notifications at start
    },
    -- Diagnostics configuration (for vim.diagnostics.config({...})) when diagnostics are on
    diagnostics = {
      virtual_text = true,
      underline = true,
    },
    -- passed to `vim.filetype.add`
    filetypes = {
      -- see `:h vim.filetype.add` for usage
      extension = {
        foo = "fooscript",
      },
      filename = {
        [".foorc"] = "fooscript",
      },
      pattern = {
        [".*/etc/foo/.*"] = "fooscript",
      },
    },
    -- vim options can be configured here
    options = {
      opt = { -- vim.opt.<key>
        relativenumber = true, -- sets vim.opt.relativenumber
        number = true, -- sets vim.opt.number
        spell = false, -- sets vim.opt.spell
        signcolumn = "yes", -- sets vim.opt.signcolumn to yes
        wrap = false, -- sets vim.opt.wrap
        expandtab = false,
        cursorline = false,
        tabstop = 8,
        shiftwidth = 8,
        showtabline = 8,
        vim.opt.rtp:append("/usr/share/vim/vimfiles"),
        vim.opt.cinoptions:append("(0");
      },
      g = { -- vim.g.<key>
        -- configure global vim variables (vim.g)
        -- NOTE: `mapleader` and `maplocalleader` must be set in the AstroNvim opts or before `lazy.setup`
        -- This can be found in the `lua/lazy_setup.lua` file
        mapleader = " ", -- sets vim.g.mapleader
        cmp_enabled = true, -- enable completion at start
        diagnostics_mode = 3, -- set the visibility of diagnostics in the UI (0=off, 1=only show in status line, 2=virtual text off, 3=all on)
        icons_enabled = true, -- disable icons in the UI (disable if no nerd font is available, requires :PackerSync after changing)
        autoformat_enabled = false, -- enable or disable auto formatting at start (lsp.formatting.format_on_save must be enabled)
        autopairs_enabled = false, -- enable autopairs at start
        ui_notifications_enabled = true, -- disable notifications when toggling UI elements
        c_syntax_for_h = 1,
        -- Vimtex
        vimtex_view_method = "zathura",
        vimtex_compiler_latexmk = {
          aux_dir = "/run/user/1000/vimtex-aux"
        },
        -- Wiki
        wiki_root = '~/Documentos/Wiki',
        wiki_journal = {
          name = "journal",
          frequency = "daily",
          date_format = {
            daily = "%Y/%m/%d",
          },
        },
        wiki_viewer = {
          png = "feh",
          jpg = "feh",
          jpeg = "feh",
        },
        infoprg = '/usr/bin/info'
      },
    },
    -- Mappings can be configured through AstroCore as well.
    -- NOTE: keycodes follow the casing in the vimdocs. For example, `<Leader>` must be capitalized
    mappings = {
      -- first key is the mode
      n = {
        -- second key is the lefthand side of the map

        -- navigate buffer tabs
        ["]b"] = { function() require("astrocore.buffer").nav(vim.v.count1) end, desc = "Next buffer" },
        ["[b"] = { function() require("astrocore.buffer").nav(-vim.v.count1) end, desc = "Previous buffer" },

        -- mappings seen under group name "Buffer"
        ["<Leader>bd"] = {
          function()
            require("astroui.status.heirline").buffer_picker(
              function(bufnr) require("astrocore.buffer").close(bufnr) end
            )
          end,
          desc = "Close buffer from tabline",
        },

        -- tables with just a `desc` key will be registered with which-key if it's installed
        -- this is useful for naming menus
        -- ["<Leader>b"] = { desc = "Buffers" },

        -- setting a mapping to false will disable it
        -- ["<C-S>"] = false,
        -- navigate buffer tabs with `H` and `L`
        L = { function() require("astrocore.buffer").nav(vim.v.count1) end, desc = "Next buffer" },
        H = { function() require("astrocore.buffer").nav(-vim.v.count1) end, desc = "Previous buffer" },

        -- mappings seen under group name "Buffer"
        ["<Leader>bD"] = {
          function()
            require("astroui.status.heirline").buffer_picker(
              function(bufnr) require("astrocore.buffer").close(bufnr) end
            )
          end,
          desc = "Pick to close",
        },
        -- tables with just a `desc` key will be registered with which-key if it's installed
        -- this is useful for naming menus
        ["<Leader>b"] = { desc = "Buffers" },
        -- quick save
        -- disable default bindings
        ["<C-Down>"] = false,
        ["<C-Left>"] = false,
        ["<C-Right>"] = false,
        ["<C-Up>"] = false,
        ["<C-h>"] = false,
        ["<C-j>"] = false,
        ["<C-k>"] = false,
        ["<C-l>"] = false,
        ["<C-q>"] = false,
        ["<C-s>"] = false,
        ["<C-r>"] = false,
        -- Competitest
        ["<C-o>"] = { "<cmd>CompetiTest receive problem<cr>", desc = "Open problem" },
        ["<C-r>"] = { "<cmd>CompetiTest run<cr>", desc = "Run problem" },
        ["q:"] = ":",
        -- second key is the lefthand side of the map
        -- mappings seen under group name "Buffer"
        ["<Leader>bn"] = { "<cmd>tabnew<cr>", desc = "New tab" },
        ["<Leader>bD"] = {
          function()
            require("astroui.status").heirline.buffer_picker(function(bufnr) require("astrocore.buffer").close(bufnr) end)
          end,
          desc = "Pick to close",
        },
        ["<Leader>bb"] = { "<cmd>tabnew<cr>", desc = "New tab" },
        ["<Leader>bc"] = { "<cmd>BufferLinePickClose<cr>", desc = "Pick to close" },
        ["<Leader>bj"] = { "<cmd>BufferLinePick<cr>", desc = "Pick to jump" },
        ["<Leader>bt"] = { "<cmd>BufferLineSortByTabs<cr>", desc = "Sort by tabs" },
        ["<Leader>lp"] = { "<cmd>ClangdToggleInlayHints<cr>", desc = "Toggle inlay hints" },
        ["<Leader>lH"] = { "<cmd>ClangdSwitchSourceHeader<cr>", desc = "Switch between source and header" },
        ["L"] =
          { function() require("astrocore.buffer").nav(vim.v.count > 0 and vim.v.count or 1) end, desc = "Next buffer" },
        ["H"] = {
          function() require("astrocore.buffer").nav(-(vim.v.count > 0 and vim.v.count or 1)) end,
          desc = "Previous buffer",
        },
        ["<F2>"] = { function() vim.lsp.buf.rename() end, desc = "Rename current symbol" },
        ["<F8>"] = {"<cmd>2TermExec cmd=\"%:p:r\"<cr>", desc = "Execute file"},
        ["et"] = {"<cmd>term %:p:r<cr>"},
        ["<C-'>"] = {"<cmd>ToggleTerm<cr>", desc = "Toggle terminal"},
        ["<C-n>"] = { "<cmd>Neotree toggle<cr>", desc = "Toggle Explorer" },
        -- tables with the `name` key will be registered with which-key if it's installed
        -- this is useful for naming menus
        ["<Leader>b"] = { desc = "Buffers" },
        -- quick save
        -- ["<C-s>"] = { ":w!<cr>", desc = "Save File" },  -- change description but the same command
        ["<Up>"] = { function() require("smart-splits").resize_up(2) end, desc = "Resize split up" },
        ["<Down>"] = { function() require("smart-splits").resize_down(2) end, desc = "Resize split down" },
        ["<Left>"] = { function() require("smart-splits").resize_left(2) end, desc = "Resize split left" },
        ["<Right>"] = { function() require("smart-splits").resize_right(2) end, desc = "Resize split right" },
        ["<Tab>"] = {
          function()
            if #vim.t.bufs > 1 then
              require("telescope.builtin").buffers { sort_mru = true, ignore_current_buffer = true }
            else
              astro_utils.notify "No other buffers open"
            end
          end,
          desc = "Switch Buffers",
        },
        ["<Leader>N"] = { "<cmd>tabnew<cr>", desc = "New Tab" },
        ["<Leader><cr>"] = { '<esc>/<++><cr>"_c4l', desc = "Next Template" },
        ["<Leader>."] = { "<cmd>cd %:p:h<cr>", desc = "Set CWD" },
        -- neogen
        ["<Leader>a"] = { desc = "󰏫 Annotate" },
        ["<Leader>a<cr>"] = { function() require("neogen").generate() end, desc = "Current" },
        ["<Leader>ac"] = { function() require("neogen").generate { type = "class" } end, desc = "Class" },
        ["<Leader>af"] = { function() require("neogen").generate { type = "func" } end, desc = "Function" },
        ["<Leader>at"] = { function() require("neogen").generate { type = "type" } end, desc = "Type" },
        ["<Leader>aF"] = { function() require("neogen").generate { type = "file" } end, desc = "File" },
        -- telescope plugin mappings
        ["<Leader>fx"] = {
          function() require("telescope").extensions.live_grep_args.live_grep_args() end,
          desc = "Find words (args)",
        },
        ["<Leader>fB"] = { "<cmd>Telescope bibtex<cr>", desc = "Find BibTeX" },
        ["<Leader>fe"] = { "<cmd>Telescope file_browser<cr>", desc = "File explorer" },
        ["<Leader>fp"] = { function() require("telescope").extensions.projects.projects {} end, desc = "Find projects" },
        ["<Leader>fT"] = { "<cmd>TodoTelescope<cr>", desc = "Find TODOs" },
        -- compiler
        ["<Leader>m"] = { desc = "󱁤 Compiler" },
        ["<Leader>mk"] = {
          function()
            vim.cmd "silent! write"
            local filename = vim.fn.expand "%:t"
            utils.async_run({ "compiler", vim.fn.expand "%:p" }, function() astro_utils.notify("Compiled " .. filename) end)
          end,
          desc = "Compile",
        },
        ["<Leader>ma"] = {
          function()
            vim.notify "Autocompile Started"
            utils.async_run({ "autocomp", vim.fn.expand "%:p" }, function() astro_utils.notify "Autocompile stopped" end)
          end,
          desc = "Auto Compile",
        },
        ["<Leader>mv"] = {
          function() vim.fn.jobstart { "opout", vim.fn.expand "%:p" } end,
          desc = "View Output",
        },
        ["<Leader>mb"] = {
          function()
            local filename = vim.fn.expand "%:t"
            utils.async_run({
              "pandoc",
              vim.fn.expand "%",
              "--pdf-engine=xelatex",
              "--variable",
              "urlcolor=blue",
              "-t",
              "beamer",
              "-o",
              vim.fn.expand "%:r" .. ".pdf",
            }, function() astro_utils.notify("Compiled " .. filename) end)
          end,
          desc = "Compile Beamer",
        },
        ["<Leader>mp"] = {
          function()
            local pdf_path = vim.fn.expand "%:r" .. ".pdf"
            if vim.fn.filereadable(pdf_path) == 1 then vim.fn.jobstart { "pdfpc", pdf_path } end
          end,
          desc = "Present Output",
        },
        ["<Leader>ml"] = { function() utils.toggle_qf() end, desc = "Logs" },
        ["<Leader>mt"] = { "<cmd>TexlabBuild<cr>", desc = "LaTeX" },
        ["<Leader>mf"] = { "<cmd>TexlabForward<cr>", desc = "Forward Search" },
        ["<Leader>r"] = { desc = " REPL" },
        ["<Leader>rr"] = { "<Plug>Send", desc = "Send to REPL" },
        ["<Leader>rl"] = { "<Plug>SendLine", desc = "Send line to REPL" },
        ["<Leader>r<cr>"] = { "<cmd>SendHere<cr>", desc = "Set REPL" },
        ["<Leader>z"] = { "<cmd>ZenMode<cr>", desc = "Zen Mode" },
        ["<Leader>s"] = { desc = "󰛔 Search/Replace" },
        ["<Leader>ss"] = { function() require("spectre").toggle() end, desc = "Toggle Spectre" },
        ["<Leader>sf"] = { function() require("spectre").open_file_search() end, desc = "Spectre (current file)" },
        ["<Leader>sw"] = {
          function() require("spectre").open_visual { select_word = true } end,
          desc = "Spectre (current word)",
        },
        ["<Leader>x"] = { desc = "󰒡 Trouble" },
        ["<Leader>xx"] = { "<cmd>TroubleToggle document_diagnostics<cr>", desc = "Document Diagnostics (Trouble)" },
        ["<Leader>xX"] = { "<cmd>TroubleToggle workspace_diagnostics<cr>", desc = "Workspace Diagnostics (Trouble)" },
        ["<Leader>xl"] = { "<cmd>TroubleToggle loclist<cr>", desc = "Location List (Trouble)" },
        ["<Leader>xq"] = { "<cmd>TroubleToggle quickfix<cr>", desc = "Quickfix List (Trouble)" },
        ["<Leader>xT"] = { "<cmd>TodoTrouble<cr>", desc = "TODOs (Trouble)" },
        -- Wiki mappings
        ["<Leader>w"] = { desc = "󰖬 Wiki" },
        ["<Leader>wn"] = { "<Plug>(wiki-open)", desc = "Open/create wiki page" },
        ["<Leader>ww"] = { "<Plug>(wiki-index)", desc = "Open wiki index" },
        ["<Leader>wx"] = { "<Plug>(wiki-reload)", desc = "Reload wiki" },
        ["<Leader>wp"] = { "<Plug>(wiki-pages)", desc = "Open wiki page" },
        ["<Leader>wt"] = { "<Plug>(wiki-tags)", desc = "Open wiki from tags" },
        ["<Leader>wd"] = { "<Plug>(wiki-page-delete)", desc = "Delete wiki page" },
        ["<Leader>wf"] = { "<Plug>(wiki-link-transform)", desc = "Transform link" },
        ["<Leader>wr"] = { "<Plug>(wiki-page-rename)", desc = "Rename wiki page" },
        ["<Leader>wT"] = { "<Plug>(wiki-toc-generate-local)", desc = "Create local table" },
        ["<Leader>wg"] = { desc = "Graphs" },
        ["<Leader>wgb"] = { "<Plug>(wiki-graph-find-backlinks)", desc = "Find backlinks" },
        ["<Leader>wbC"] = { "<Plug>(wiki-graph-check-links-g)", desc = "Check wiki for broken links" },
        ["<Leader>wbc"] = { "<Plug>(wiki-graph-check-links)", desc = "Check page for broken links" },
        ["<Leader>wbi"] = { "<Plug>(wiki-graph-in)", desc = "Show link graph in to page" },
        ["<Leader>wbo"] = { "<Plug>(wiki-graph-out)", desc = "Show link graph out of page" },
        ["<Leader>wbO"] = { "<Plug>(wiki-graph-check-orphans)", desc = "Check wiki for orphan pages" },
        ["<Leader>wbr"] = { "<Plug>(wiki-graph-related)", desc = "Open page link relations" },
        ["<Leader>wl"] = { desc = "Links" },
        ["<Leader>wlh"] = { "<Plug>(wiki-link-extract-header)", desc = "Set link titles from first header" },
        ["<Leader>wli"] = { "<Plug>(wiki-link-incoming-toggle)", desc = "Toggle incoming links" },
        ["<Leader>wlI"] = { "<Plug>(wiki-link-incoming-hover)", desc = "Show incoming links" },
        ["<Leader>wll"] = { "<Plug>(wiki-link-show)", desc = "Show link info" },
        ["<Leader>ws"] = { desc = "Tags" },
        ["<Leader>wsl"] = { "<Plug>(wiki-tag-list)", desc = "List all tags" },
        ["<Leader>wsn"] = { "<Plug>(wiki-tag-rename)", desc = "Rename tag" },
        ["<Leader>wsr"] = { "<Plug>(wiki-tag-reload)", desc = "Reload tags" },
        ["<Leader>wss"] = { "<Plug>(wiki-tag-search)", desc = "List pages with tag" },
        ["<Leader>w<space>"] = { desc = "Journal" },
        -- ["<Leader>w<space>w"] = { "<Plug>(wiki-journal)Go<enter><esc>!!date +\\%R<cr>I# <C-o>o<enter>", desc = "Open wiki journal" },
        ["<Leader>w<space>w"] = { "<cmd>TermExec cmd='fish -c journal;exit'<cr>", desc = "Open journal" },
        ["<C-s>"] = { ":w!<cr>", desc = "Save File" },  -- change description but the same command
        ["<C-l>"] = { function() require("luasnip").jump(1) end, desc = "Jump to next snippet" },
      },
    },
  },
}
