if vim.g.loaded_copilot_chat then
  return
end

local min_version = '0.10.0'
if vim.fn.has('nvim-' .. min_version) ~= 1 then
  vim.notify_once(('CopilotChat.nvim requires Neovim >= %s'):format(min_version), vim.log.levels.ERROR)
  return
end

local group = vim.api.nvim_create_augroup('CopilotChat', {})

-- Setup highlights
local function setup_highlights()
  vim.api.nvim_set_hl(0, 'CopilotChatHeader', { link = '@markup.heading.2.markdown', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatSeparator', { link = '@punctuation.special.markdown', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatSelection', { link = 'Visual', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatStatus', { link = 'DiagnosticHint', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatHelp', { link = 'DiagnosticInfo', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatResource', { link = 'Constant', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatTool', { link = 'Function', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatPrompt', { link = 'Statement', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatModel', { link = 'Type', default = true })
  vim.api.nvim_set_hl(0, 'CopilotChatUri', { link = 'Underlined', default = true })

  vim.api.nvim_set_hl(0, 'CopilotChatAnnotation', { link = 'ColorColumn', default = true })
  local fg = vim.api.nvim_get_hl(0, { name = 'CopilotChatStatus', link = false }).fg
  local bg = vim.api.nvim_get_hl(0, { name = 'CopilotChatAnnotation', link = false }).bg
  vim.api.nvim_set_hl(0, 'CopilotChatAnnotationHeader', { fg = fg, bg = bg })
end
vim.api.nvim_create_autocmd('ColorScheme', {
  group = group,
  callback = function()
    setup_highlights()
  end,
})
setup_highlights()

vim.api.nvim_create_autocmd('FileType', {
  pattern = 'copilot-chat',
  group = group,
  callback = vim.schedule_wrap(function()
    vim.cmd.syntax('match CopilotChatResource "#\\S\\+"')
    vim.cmd.syntax('match CopilotChatTool "@\\S\\+"')
    vim.cmd.syntax('match CopilotChatPrompt "/\\S\\+"')
    vim.cmd.syntax('match CopilotChatModel "\\$\\S\\+"')
    vim.cmd.syntax('match CopilotChatUri "##\\S\\+"')
  end),
})

-- Setup commands
vim.api.nvim_create_user_command('CopilotChat', function(args)
  local chat = require('CopilotChat')
  local input = args.args
  if input and vim.trim(input) ~= '' then
    chat.ask(input)
  else
    chat.open()
  end
end, {
  nargs = '*',
  force = true,
  range = true,
})
vim.api.nvim_create_user_command('CopilotChatPrompts', function()
  local chat = require('CopilotChat')
  chat.select_prompt()
end, { force = true, range = true })
vim.api.nvim_create_user_command('CopilotChatModels', function()
  local chat = require('CopilotChat')
  chat.select_model()
end, { force = true })
vim.api.nvim_create_user_command('CopilotChatOpen', function()
  local chat = require('CopilotChat')
  chat.open()
end, { force = true })
vim.api.nvim_create_user_command('CopilotChatClose', function()
  local chat = require('CopilotChat')
  chat.close()
end, { force = true })
vim.api.nvim_create_user_command('CopilotChatToggle', function()
  local chat = require('CopilotChat')
  chat.toggle()
end, { force = true })
vim.api.nvim_create_user_command('CopilotChatStop', function()
  local chat = require('CopilotChat')
  chat.stop()
end, { force = true })
vim.api.nvim_create_user_command('CopilotChatReset', function()
  local chat = require('CopilotChat')
  chat.reset()
end, { force = true })

local function complete_load()
  local chat = require('CopilotChat')
  local options = vim.tbl_map(function(file)
    return vim.fn.fnamemodify(file, ':t:r')
  end, vim.fn.glob(chat.config.history_path .. '/*', true, true))

  if not vim.tbl_contains(options, 'default') then
    table.insert(options, 1, 'default')
  end

  return options
end
vim.api.nvim_create_user_command('CopilotChatSave', function(args)
  local chat = require('CopilotChat')
  chat.save(args.args)
end, { nargs = '*', force = true, complete = complete_load })
vim.api.nvim_create_user_command('CopilotChatLoad', function(args)
  local chat = require('CopilotChat')
  chat.load(args.args)
end, { nargs = '*', force = true, complete = complete_load })

-- Store the current directory to window when directory changes
-- I dont think there is a better way to do this that functions
-- with "rooter" plugins, LSP and stuff as vim.fn.getcwd() when
-- i pass window number inside doesnt work
vim.api.nvim_create_autocmd({ 'VimEnter', 'WinEnter', 'DirChanged' }, {
  group = group,
  callback = function()
    vim.w.cchat_cwd = vim.fn.getcwd()
  end,
})

-- Setup treesitter
vim.treesitter.language.register('markdown', 'copilot-chat')

vim.g.loaded_copilot_chat = true
