-- LidPanels_Editor_CustomDropdown.lua
-- Reusable custom dropdown control for long editor lists.

local API = _G.LIDPANELS_API
if type(API) ~= "table" then
  error("LidPanels missing API table")
end

local function PublishApi(name, value)
  _G[name] = value
  API[name] = value
end

local function CreateCustomDropdownControl(editor, parent, opts)
  opts = opts or {}
  local dropdownWidth = tonumber(opts.width) or 220
  local buttonHeight = tonumber(opts.buttonHeight) or 24
  local rowHeight = tonumber(opts.rowHeight) or 18
  local accentR, accentG, accentB = 0.6588, 0.4784, 0.9098

  local root = CreateFrame("Frame", nil, parent)
  root.__lidpanelsCustomDropdown = true
  root.dropdownWidth = dropdownWidth
  root.buttonHeight = buttonHeight
  root.rowHeight = rowHeight
  root.selectedValue = nil
  root.displayText = tostring(opts.text or "None")
  root:SetSize(dropdownWidth + 24, buttonHeight)

  local button = CreateFrame("Button", nil, root, "BackdropTemplate")
  button:SetPoint("TOPLEFT", 12, 0)
  button:SetSize(dropdownWidth, buttonHeight)
  button:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
  })
  button:SetBackdropColor(0.06, 0.08, 0.11, 0.96)
  button:SetBackdropBorderColor(accentR, accentG, accentB, 0.95)

  local highlight = button:CreateTexture(nil, "HIGHLIGHT")
  highlight:SetAllPoints()
  highlight:SetTexture("Interface\\Buttons\\WHITE8x8")
  highlight:SetVertexColor(accentR, accentG, accentB, 0.10)

  local text = button:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  text:SetPoint("LEFT", 8, 0)
  text:SetPoint("RIGHT", -20, 0)
  text:SetJustifyH("LEFT")
  text:SetText(root.displayText)
  button.text = text

  local arrow = button:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  arrow:SetPoint("RIGHT", -8, 0)
  arrow:SetText("v")
  button.arrow = arrow

  local popup = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
  popup:SetClampedToScreen(true)
  popup:SetFrameStrata("TOOLTIP")
  popup:SetToplevel(true)
  popup:EnableMouseWheel(true)
  popup:Hide()
  popup:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
  })
  popup:SetBackdropColor(0.04, 0.05, 0.08, 0.98)
  popup:SetBackdropBorderColor(accentR, accentG, accentB, 0.96)
  root.popup = popup

  local rows = {}

  local function EnsureRow(index)
    if rows[index] then
      return rows[index]
    end

    local row = CreateFrame("Button", nil, popup)
    row:SetHeight(rowHeight)
    if index == 1 then
      row:SetPoint("TOPLEFT", 6, -6)
      row:SetPoint("TOPRIGHT", -6, -6)
    else
      row:SetPoint("TOPLEFT", rows[index - 1], "BOTTOMLEFT", 0, 0)
      row:SetPoint("TOPRIGHT", rows[index - 1], "BOTTOMRIGHT", 0, 0)
    end
    row:EnableMouseWheel(true)

    local rowHighlight = row:CreateTexture(nil, "HIGHLIGHT")
    rowHighlight:SetAllPoints()
    rowHighlight:SetTexture("Interface\\Buttons\\WHITE8x8")
    rowHighlight:SetVertexColor(accentR, accentG, accentB, 0.12)

    local selected = row:CreateTexture(nil, "ARTWORK")
    selected:SetTexture("Interface\\Buttons\\WHITE8x8")
    selected:SetSize(4, 12)
    selected:SetPoint("LEFT", 2, 0)
    selected:SetVertexColor(accentR, accentG, accentB, 0.95)
    selected:Hide()
    row.selectedMark = selected

    local icon = row:CreateTexture(nil, "ARTWORK")
    icon:SetSize(16, 16)
    icon:SetPoint("LEFT", 10, 0)
    icon:Hide()
    row.icon = icon

    local label = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    label:SetPoint("LEFT", 12, 0)
    label:SetPoint("RIGHT", -8, 0)
    label:SetJustifyH("LEFT")
    row.text = label

    row:SetScript("OnClick", function(self)
      local entry = self.entry
      if type(entry) ~= "table" or entry.disabled or entry.isTitle then
        return
      end
      if type(entry.func) == "function" then
        entry.func()
      end
      if entry.keepShownOnClick then
        root:RefreshMenu()
      else
        root:CloseMenu()
      end
    end)

    row:SetScript("OnMouseWheel", function(_, delta)
      local menu = root.activeMenu
      if type(menu) ~= "table" or type(menu.onMouseWheel) ~= "function" then
        return
      end
      local changed = menu.onMouseWheel(delta)
      if changed then
        root:RefreshMenu()
      end
    end)

    rows[index] = row
    return row
  end

  local function HidePopup()
    popup:Hide()
    root.activeMenu = nil
    button.arrow:SetText("v")
    if editor and editor.__lidpanelsOpenDropdown == root then
      editor.__lidpanelsOpenDropdown = nil
    end
  end

  local function ApplyRowAppearance(row, entry)
    entry = entry or {}
    row.entry = entry
    row:Show()
    row.selectedMark:SetShown(entry.checked and (not entry.isTitle) and (not entry.notCheckable))

    local iconTexture = entry.icon
    if iconTexture and iconTexture ~= "" then
      row.icon:SetTexture(iconTexture)
      row.icon:SetSize(tonumber(entry.iconSize) or 16, tonumber(entry.iconSize) or 16)
      local iconOffset = tonumber(entry.iconXOffset) or 0
      row.icon:ClearAllPoints()
      row.icon:SetPoint("LEFT", 10 + iconOffset, 0)
      row.icon:Show()
      row.text:ClearAllPoints()
      row.text:SetPoint("LEFT", row.icon, "RIGHT", 6, 0)
      row.text:SetPoint("RIGHT", -8, 0)
    else
      row.icon:Hide()
      row.text:ClearAllPoints()
      row.text:SetPoint("LEFT", 12, 0)
      row.text:SetPoint("RIGHT", -8, 0)
    end

    row.text:SetText(tostring(entry.text or ""))
    if entry.isTitle then
      row.text:SetTextColor(1.00, 0.82, 0.28, 1.00)
    elseif entry.disabled then
      row.text:SetTextColor(0.55, 0.55, 0.55, 1.00)
    elseif entry.checked then
      row.text:SetTextColor(0.92, 0.86, 0.99, 1.00)
    else
      row.text:SetTextColor(1.00, 1.00, 1.00, 1.00)
    end
    row:EnableMouse((not entry.disabled) and (not entry.isTitle))
  end

  function root:SetSelectedValue(value)
    self.selectedValue = value
  end

  function root:GetSelectedValue()
    return self.selectedValue
  end

  function root:SetText(value)
    self.displayText = tostring(value or "")
    button.text:SetText(self.displayText)
  end

  function root:GetText()
    return self.displayText
  end

  function root:SetMenuBuilder(fn)
    self.menuBuilder = fn
  end

  function root:RefreshMenu()
    if type(self.menuBuilder) ~= "function" then
      return false
    end

    local menu = self.menuBuilder(self) or {}
    local entries = type(menu.entries) == "table" and menu.entries or {}
    local popupWidth = tonumber(menu.width) or self.dropdownWidth
    local entryCount = #entries
    if entryCount < 1 then
      entries = {
        { text = "No entries", disabled = true, notCheckable = true },
      }
      entryCount = 1
    end

    popup:ClearAllPoints()
    popup:SetPoint("TOPLEFT", button, "BOTTOMLEFT", 0, -2)
    popup:SetWidth(popupWidth)
    popup:SetHeight((entryCount * rowHeight) + 12)

    self.activeMenu = menu
    for i = 1, entryCount do
      local row = EnsureRow(i)
      ApplyRowAppearance(row, entries[i])
    end
    for i = entryCount + 1, #rows do
      rows[i]:Hide()
      rows[i].entry = nil
    end

    return true
  end

  function root:CloseMenu()
    HidePopup()
  end

  function root:OpenMenu()
    if type(self.menuBuilder) ~= "function" then
      return false
    end
    if editor and editor.__lidpanelsOpenDropdown and editor.__lidpanelsOpenDropdown ~= self then
      editor.__lidpanelsOpenDropdown:CloseMenu()
    end
    if not self:RefreshMenu() then
      return false
    end
    if editor then
      editor.__lidpanelsOpenDropdown = self
    end
    popup:Show()
    button.arrow:SetText("^")
    return true
  end

  function root:ToggleMenu()
    if popup:IsShown() then
      self:CloseMenu()
      return
    end
    self:OpenMenu()
  end

  button:SetScript("OnClick", function()
    root:ToggleMenu()
  end)

  popup:SetScript("OnMouseWheel", function(_, delta)
    local menu = root.activeMenu
    if type(menu) ~= "table" or type(menu.onMouseWheel) ~= "function" then
      return
    end
    local changed = menu.onMouseWheel(delta)
    if changed then
      root:RefreshMenu()
    end
  end)

  root.button = button
  root.SetDisplayText = root.SetText
  root:SetText(root.displayText)
  root:HookScript("OnHide", function()
    root:CloseMenu()
  end)
  if editor and editor.HookScript then
    editor:HookScript("OnHide", function()
      if editor.__lidpanelsOpenDropdown == root then
        root:CloseMenu()
      end
    end)
  end

  return root
end

PublishApi("LIDPANELS_CreateCustomDropdownControl", CreateCustomDropdownControl)
