--[[ UI/Window.lua - main frame: tabs, 3-column layout, resize, ESC (spec F1/7). ]]

local _, ns = ...
local S = ns.Style
local W = ns.Widgets
ns.UI = ns.UI or {}
local UI = ns.UI

local built = false

local function Build()
  if built then return end
  built = true

  local f = W.Panel(UIParent)
  f:SetFrameStrata("HIGH")
  f:SetSize(S.window.w, S.window.h)
  local pos = ns.db.settings.windowPos
  if pos then f:SetPoint(pos.point, UIParent, pos.point, pos.x, pos.y)
  else f:SetPoint("CENTER") end
  f:SetMovable(true)
  f:SetResizable(true)
  if f.SetResizeBounds then f:SetResizeBounds(S.window.minW, S.window.minH) end
  f:EnableMouse(true)
  f:SetClampedToScreen(true)
  f:Hide()
  UI.frame = f
  _G["BlueprintBazaarFrame"] = f
  tinsert(UISpecialFrames, "BlueprintBazaarFrame")

  -- title bar (drag)
  local bar = CreateFrame("Frame", nil, f)
  bar:SetPoint("TOPLEFT")
  bar:SetPoint("TOPRIGHT")
  bar:SetHeight(30)
  bar:EnableMouse(true)
  bar:RegisterForDrag("LeftButton")
  bar:SetScript("OnDragStart", function() f:StartMoving() end)
  bar:SetScript("OnDragStop", function()
    f:StopMovingOrSizing()
    local point, _, _, x, y = f:GetPoint()
    ns.db.settings.windowPos = { point = point, x = x, y = y }
  end)
  local title = W.Text(bar, S.size.title, S.gold)
  title:SetPoint("LEFT", S.pad, 0)
  title:SetText("BlueprintBazaar")

  local close = CreateFrame("Button", nil, f, "UIPanelCloseButton")
  close:SetPoint("TOPRIGHT", 2, 2)
  close:SetScript("OnClick", function() f:Hide() end)

  -- resize grip
  local grip = CreateFrame("Button", nil, f)
  grip:SetSize(14, 14)
  grip:SetPoint("BOTTOMRIGHT", -2, 2)
  grip:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
  grip:SetScript("OnMouseDown", function() f:StartSizing("BOTTOMRIGHT") end)
  grip:SetScript("OnMouseUp", function()
    f:StopMovingOrSizing()
    ns.bus:Fire("WINDOW_RESIZED")
    -- re-run the detail layout too: how many item lines fit depends on height
    if UI.RelayoutDetail then UI.RelayoutDetail() end
  end)

  -- tabs
  local tabs = { { key = "browse", label = "Browse" }, { key = "mine", label = "My Blueprints" },
                 { key = "favs", label = "Favorites" } }
  UI.tabButtons = {}
  local tx = S.pad
  for _, t in ipairs(tabs) do
    local b = W.Button(f, t.label, function() UI.SelectTab(t.key) end)
    b:SetPoint("TOPLEFT", tx, -32)
    tx = tx + b:GetWidth() + 4
    UI.tabButtons[t.key] = b
  end

  -- "Favorites (3)": the count is what tells you the tab has anything in it.
  -- The button keeps the width it was built with so the row does not shuffle
  -- every time a star is clicked; two digits fit in the slack.
  function UI.RefreshFavCount()
    local b = UI.tabButtons.favs
    if not b then return end
    -- Count only what the tab can actually show. A code inspected with
    -- /bb code is not a library entry, so a star on one left the count
    -- reading 1 above an empty shelf.
    local lib = {}
    for _, e in ipairs((ns.Library and ns.Library.entries) or {}) do lib[e.id] = true end
    local n = 0
    for id in pairs(ns.db.favorites or {}) do
      if lib[id] then n = n + 1 end
    end
    b.text:SetText(n > 0 and ("Favorites (" .. n .. ")") or "Favorites")
    local need = b.text:GetStringWidth() + 20
    if need > b:GetWidth() then b:SetWidth(need) end
  end
  UI.RefreshFavCount()

  -- 3-column content region
  local content = CreateFrame("Frame", nil, f)
  content:SetPoint("TOPLEFT", S.pad, -60)
  content:SetPoint("BOTTOMRIGHT", -S.pad, S.pad)
  UI.content = content

  local rail = W.Panel(content, true)
  rail:SetPoint("TOPLEFT")
  rail:SetPoint("BOTTOMLEFT")
  rail:SetWidth(S.rail)
  UI.rail = rail

  local detail = W.Panel(content, true)
  detail:SetPoint("TOPRIGHT")
  detail:SetPoint("BOTTOMRIGHT")
  detail:SetWidth(S.detail)
  -- last line of defence: nothing in the detail pane may draw outside it,
  -- however small the user makes the window
  if detail.SetClipsChildren then detail:SetClipsChildren(true) end
  UI.detailPanel = detail

  local gridHost = CreateFrame("Frame", nil, content)
  gridHost:SetPoint("TOPLEFT", rail, "TOPRIGHT", S.pad, 0)
  gridHost:SetPoint("BOTTOMRIGHT", detail, "BOTTOMLEFT", -S.pad, 0)
  UI.gridHost = gridHost

  if not C_HousingBlueprint then
    local warn = W.Text(content, S.size.body, S.red)
    warn:SetPoint("TOP", gridHost, "TOP", 0, -4)
    warn:SetText("Housing Blueprints API not found - BlueprintBazaar requires patch 12.1.")
  end

  if UI.BuildFilters then UI.BuildFilters(rail) end
  if UI.BuildGrid then UI.BuildGrid(gridHost) end
  if UI.BuildDetail then UI.BuildDetail(detail) end

  UI.activeTab = "browse"
  UI.SelectTab("browse")
end

function UI.SelectTab(key)
  UI.activeTab = key
  for k, b in pairs(UI.tabButtons or {}) do
    if k == key then
      b.text:SetTextColor(S.gold[1], S.gold[2], S.gold[3])
    else
      b.text:SetTextColor(S.text[1], S.text[2], S.text[3])
    end
  end
  if key == "mine" then
    if UI.gridScroll then UI.gridScroll:Hide() end
    if UI.emptyText then UI.emptyText:Hide() end
    if ns.MyBlueprints then ns.MyBlueprints.Show() end
  else
    if ns.MyBlueprints then ns.MyBlueprints.Hide() end
    if UI.gridScroll then UI.gridScroll:Show() end
    if UI.RefreshGrid then UI.RefreshGrid() end
  end
end

function UI.Toggle()
  Build()
  if UI.frame:IsShown() then UI.frame:Hide()
  else
    UI.frame:Show()
    if UI.RefreshGrid then UI.RefreshGrid() end
    -- Learn the house once. Ceilings ride on any contents reply, but when the
    -- catalog already knows ownership no reply is ever asked for, and every
    -- card would sit on the advisory "Lvl 7+" instead of the plain "Lvl 7" that
    -- says it will not fit. One request, first entry with a code, one time.
    if ns.HouseLevel and not ns.HouseLevel.Ceilings() and ns.Guard.Has("contents") then
      for _, e in ipairs((ns.Library and ns.Library.entries) or {}) do
        if e.code then UI.QueueScoreRequest(e); break end
      end
    end
  end
end
