---@type parinfer_lib
local parinfer_lib = require("parinfer_lib")

---@class parinfer.decorations
---@field private responses table<number, parinfer_response?>
local export = {}
export.responses = {}
export.ns = vim.api.nvim_create_namespace("parinfer")
---@type vim.api.keyset.set_decoration_provider
export.provider = {
  on_buf = function(_, bufnr)
    ---@diagnostic disable-next-line: redundant-return-value
    return export.responses[bufnr] ~= nil
  end,
  on_win = function(_, winid, bufnr, toprow, botrow)
    local response = export.responses[bufnr]
    if response == nil then
      return false
    end
    local ns = export.ns
    vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
    local lines = vim.api.nvim_buf_get_lines(bufnr, toprow, botrow + 1, false)
    if response.tab_stops ~= nil then
      ---@type vim.api.keyset.set_extmark
      local extmark_opts = { ephemeral = true, hl_group = "DiffAdd", hl_mode = "combine" }
      for _, tab_stop in ipairs(response.tab_stops) do
        local line_no = tab_stop.line_no
        if line_no >= toprow and line_no <= botrow then
          local line = lines[line_no - toprow + 1]
          local x = parinfer_lib.to_bytepos(line, tab_stop.x)
          extmark_opts.end_col = x + 1
          extmark_opts.end_row = line_no
          vim.api.nvim_buf_set_extmark(bufnr, ns, line_no, x, extmark_opts)
        end
      end
    end
    if response.paren_trails ~= nil then
      ---@type vim.api.keyset.set_extmark
      local extmark_opts = { ephemeral = true, hl_group = "DiffChange", hl_mode = "combine" }
      for _, paren_trail in ipairs(response.paren_trails) do
        local line_no = paren_trail.line_no
        if line_no >= toprow and line_no <= botrow then
          local line = lines[line_no - toprow + 1]
          local start_x = parinfer_lib.to_bytepos(line, paren_trail.start_x)
          extmark_opts.end_row = line_no
          extmark_opts.end_col = parinfer_lib.to_bytepos(line, paren_trail.end_x)
          vim.api.nvim_buf_set_extmark(bufnr, ns, line_no, start_x, extmark_opts)
        end
      end
    end
    vim.api.nvim__redraw({ win = winid, valid = false })
  end,
}

export.attach = function(parinfer_responses)
  export.responses = parinfer_responses
  vim.api.nvim_set_decoration_provider(export.ns, export.provider)
end

export.detach = function()
  export.responses = {}
  vim.api.nvim_set_decoration_provider(export.ns, {})
end

return export
