local _, ns = ...

local CUSTOM_ICON_TEXTURE = "Interface\\AddOns\\DecorDrops\\Media\\minimapicon.png"
local RING_TEXTURE = "Interface\\Minimap\\MiniMap-TrackingBorder"
local minimapShapes = {
  ["ROUND"] = { true, true, true, true },
  ["SQUARE"] = { false, false, false, false },
  ["CORNER-TOPLEFT"] = { false, false, false, true },
  ["CORNER-TOPRIGHT"] = { false, false, true, false },
  ["CORNER-BOTTOMLEFT"] = { false, true, false, false },
  ["CORNER-BOTTOMRIGHT"] = { true, false, false, false },
  ["SIDE-LEFT"] = { false, true, false, true },
  ["SIDE-RIGHT"] = { true, false, true, false },
  ["SIDE-TOP"] = { false, false, true, true },
  ["SIDE-BOTTOM"] = { true, true, false, false },
  ["TRICORNER-TOPLEFT"] = { false, true, true, true },
  ["TRICORNER-TOPRIGHT"] = { true, false, true, true },
  ["TRICORNER-BOTTOMLEFT"] = { true, true, false, true },
  ["TRICORNER-BOTTOMRIGHT"] = { true, true, true, false },
}
local MINIMAP_SNAP_RADIUS = 5

local function SetAddonIcon(texture)
  texture:SetTexture(CUSTOM_ICON_TEXTURE)
  texture:SetTexCoord(0.08, 0.92, 0.08, 0.92)
end

local function EnsureMinimapDefaults()
  DecorDropsDB.minimap = DecorDropsDB.minimap or {}
  if (DecorDropsDB.minimap.layoutVersion or 0) < 10 then
    DecorDropsDB.minimap.angle = 220
    DecorDropsDB.minimap.userPlaced = false
    DecorDropsDB.minimap.layoutVersion = 10
  end

  if not DecorDropsDB.minimap.userPlaced then
    DecorDropsDB.minimap.angle = 220
  else
    if DecorDropsDB.minimap.angle == nil then
      DecorDropsDB.minimap.angle = 220
    end
  end
end

local function UpdateButtonPosition(button)
  EnsureMinimapDefaults()

  local angle = math.rad(DecorDropsDB.minimap.angle or 225)
  local x, y = math.cos(angle), math.sin(angle)
  local q = 1
  if x < 0 then
    q = q + 1
  end
  if y > 0 then
    q = q + 2
  end

  local minimapShape = (GetMinimapShape and GetMinimapShape()) or "ROUND"
  local quadTable = minimapShapes[minimapShape] or minimapShapes.ROUND
  local w = (Minimap:GetWidth() / 2) + MINIMAP_SNAP_RADIUS
  local h = (Minimap:GetHeight() / 2) + MINIMAP_SNAP_RADIUS

  if quadTable[q] then
    x, y = x * w, y * h
  else
    local diagRadiusW = math.sqrt(2 * (w ^ 2)) - 10
    local diagRadiusH = math.sqrt(2 * (h ^ 2)) - 10
    x = math.max(-w, math.min(x * diagRadiusW, w))
    y = math.max(-h, math.min(y * diagRadiusH, h))
  end

  button:ClearAllPoints()
  button:SetPoint("CENTER", Minimap, "CENTER", x, y)
end

local function Atan2(y, x)
  if math.atan2 then
    return math.atan2(y, x)
  end

  local ok, value = pcall(math.atan, y, x)
  if ok and value then
    return value
  end

  if x == 0 then
    return y >= 0 and (math.pi / 2) or (-math.pi / 2)
  end

  local angle = math.atan(y / x)
  if x < 0 then
    angle = angle + math.pi
  end
  return angle
end

local function UpdatePositionFromCursor(button)
  local scale = Minimap:GetEffectiveScale()
  local cursorX, cursorY = GetCursorPosition()
  local minimapX, minimapY = Minimap:GetCenter()
  local x = (cursorX / scale) - minimapX
  local y = (cursorY / scale) - minimapY

  local angle = math.deg(Atan2(y, x))
  if angle < 0 then
    angle = angle + 360
  end

  DecorDropsDB.minimap.angle = angle
  DecorDropsDB.minimap.userPlaced = true
  UpdateButtonPosition(button)
end

function ns.CreateMinimapButton()
  if ns.MinimapButton then
    return
  end

  EnsureMinimapDefaults()

  local button = CreateFrame("Button", "DecorDropsMinimapButton", Minimap)
  button:SetSize(32, 32)
  button:SetClampedToScreen(true)
  button:SetFrameStrata("MEDIUM")
  button:SetFrameLevel(8)
  button:RegisterForClicks("LeftButtonUp")
  button:RegisterForDrag("LeftButton")

  local icon = button:CreateTexture(nil, "BACKGROUND")
  SetAddonIcon(icon)
  icon:SetPoint("TOPLEFT", 7, -6)
  icon:SetPoint("BOTTOMRIGHT", -6, 5)
  button.icon = icon

  local border = button:CreateTexture(nil, "OVERLAY")
  border:SetTexture(RING_TEXTURE)
  border:SetSize(53, 53)
  border:SetPoint("TOPLEFT")

  button:SetScript("OnClick", function()
    if ns.ToggleMainFrame then
      ns.ToggleMainFrame()
    end
  end)

  button:SetScript("OnDragStart", function(self)
    self:SetScript("OnUpdate", UpdatePositionFromCursor)
  end)

  button:SetScript("OnDragStop", function(self)
    self:SetScript("OnUpdate", nil)
    UpdatePositionFromCursor(self)
  end)

  button:SetScript("OnEnter", function(self)
    GameTooltip:SetOwner(self, "ANCHOR_LEFT")
    GameTooltip:AddLine("DecorDrops")
    GameTooltip:AddLine("Left-click: Toggle menu", 0.8, 0.8, 0.8)
    GameTooltip:AddLine("Drag: Move button", 0.8, 0.8, 0.8)
    GameTooltip:Show()
  end)

  button:SetScript("OnLeave", function()
    GameTooltip_Hide()
  end)

  UpdateButtonPosition(button)
  ns.MinimapButton = button
end
