local fileutils = require('lsp-toggle.fileutils')
local window = require('lsp-toggle.window')
local utils = require('lsp-toggle.utils')

---@class LspToggle.Opts
local defaults = {
	--- If less than `1`, this will revert back to `20`
	max_height = 20,

	--- If less than `1`, this will revert back to `30`
	max_width = 30,

	--- A list of LSP server names to exclude,
	--- e.g. `{ 'lua_ls', 'clangd' }` and so on...
	---@type string[]
	exclude_lsp = {},

	---@type string[]|'double'|'none'|'rounded'|'shadow'|'single'|'solid'
	border = { '╔', '-', '╗', '║', '╝', '═', '╚', '║' },

	-- Enable/Disable caching
	--
	-- Enabled by default
	---@type boolean
	cache = true,

	-- File type caching or file name caching
	-- Uses the file type instead of file name width caches.
	--
	-- For example:
	-- - all typescript files `'file_type'`
	-- - specific files `'file_name'`
	--
	-- Set to `'file_type'` by default
	---@type 'file_type'|'file_name'
	cache_type = 'file_type',

	--- Load LSPs by default regardless of cache
	--- if enabled, no LSPs will be loaded by default
	---
	--- This is disabled by default
	---@type boolean
	exclusive_mode = false,
}

---@class LspToggleConfig
local M = {}

---@type LspToggle.Opts
M.options = {}

---@param opts? LspToggle.Opts
function M.setup(opts)
	M.options = vim.tbl_deep_extend('keep', opts or {}, defaults)

	if M.options.max_height < 1 then
		M.options.max_height = defaults.max_height
	end

	if M.options.max_width < 1 then
		M.options.max_width = defaults.max_width
	end

	M.setup_autocmds()
end

---@param bufnr integer|nil
function M.setup_lsps(bufnr)
	if bufnr then
		fileutils.file_type = vim.bo[bufnr].filetype
	end
	utils.merge_table_pf() -- merge saved data before enabling/disabling clients
	for _, tb_server in pairs(utils.clients) do
		vim.lsp.enable(tb_server.server_name, tb_server.enabled)
	end
end

function M.setup_autocmds()
	local augroup = vim.api.nvim_create_augroup('lsp-toggle', { clear = true })

	vim.api.nvim_create_autocmd('LspAttach', {
		group = augroup,
		callback = function()
			if vim.bo.buftype ~= '' then
				return
			end
			-- INFO: Buffer has to be 0, window contexts count as buffer attaches
			-- will cause memory leak.
			fileutils.set_file_path(vim.api.nvim_buf_get_name(0))
			M.setup_lsps()
		end,
	})

	vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, {
		group = augroup,
		callback = function(args)
			if vim.bo[args.buf].buftype ~= '' then
				return
			end
			fileutils.set_file_path(vim.api.nvim_buf_get_name(args.buf))
			M.setup_lsps(args.buf)
		end,
	})

	vim.api.nvim_create_autocmd('BufLeave', {
		group = augroup,
		callback = function()
			window.close_window()
		end,
	})
end

return M

-- vim:ts=4:sts=4:sw=0:noet:ai:si:sta:
