-- Start Up
local ADDON_NAME, NS = ...
local L = LibStub("AceLocale-3.0"):GetLocale("MDungeonTeleports")

if not MDungeonTeleports then
   MDungeonTeleports = {}
end

if not MDungeonTeleports.PortalLibraryRaidPos then
   MDungeonTeleports.PortalLibraryRaidPos = {x = 1110, y = 198}
end

if MDungeonTeleports.showTooltips == nil then
   MDungeonTeleports.showTooltips = false
end

if MDungeonTeleports.ShiftDragToggle == nil then
    MDungeonTeleports.ShiftDragToggle = false
end

-- Save Function
local function SavePortalLibraryRaidPosition()
   local DungeonFrame = PVEFrame
   if DungeonFrame then
       local frameScale = PortalLibraryRaid:GetEffectiveScale()
       local parentScale = DungeonFrame:GetEffectiveScale()

       local PortalLibraryRaidRight = PortalLibraryRaid:GetRight() * frameScale
       local PortalLibraryRaidBottom = PortalLibraryRaid:GetBottom() * frameScale
       local dungeonRight = DungeonFrame:GetRight() * parentScale
       local dungeonBottom = DungeonFrame:GetBottom() * parentScale

       local offsetX = (PortalLibraryRaidRight - dungeonRight) / parentScale
       local offsetY = (PortalLibraryRaidBottom - dungeonBottom) / parentScale

       MDungeonTeleports.PortalLibraryRaidPos = {x = offsetX, y = offsetY}
   end
end

-- Load Function
local function LoadPortalLibraryRaidPosition()
   local VarVersionRL = 1
   if MDungeonTeleports.VarVersionRL == nil or MDungeonTeleports.VarVersionRL < VarVersionRL then
       MDungeonTeleports.VarVersionRL = VarVersionRL
       MDungeonTeleports.PortalLibraryRaidPos = {x = 1110, y = 198}
   end
   local DungeonFrame = PVEFrame
   if DungeonFrame and MDungeonTeleports.PortalLibraryRaidPos then
       local pos = MDungeonTeleports.PortalLibraryRaidPos

       local frameScale = PortalLibraryRaid:GetEffectiveScale()
       local parentScale = DungeonFrame:GetEffectiveScale()

       local adjustedX = pos.x * parentScale / frameScale
       local adjustedY = pos.y * parentScale / frameScale

       PortalLibraryRaid:ClearAllPoints()
       PortalLibraryRaid:SetPoint("BOTTOMRIGHT", DungeonFrame, "BOTTOMRIGHT", adjustedX, adjustedY)
   end
end

-- Reattach Function
local function ReattachPortalLibraryRaid()
   local DungeonFrame = PVEFrame
   if DungeonFrame and MDungeonTeleports.PortalLibraryRaidPos then
       local pos = MDungeonTeleports.PortalLibraryRaidPos

       local frameScale = PortalLibraryRaid:GetEffectiveScale()
       local parentScale = DungeonFrame:GetEffectiveScale()

       local adjustedX = pos.x * parentScale / frameScale
       local adjustedY = pos.y * parentScale / frameScale

       PortalLibraryRaid:ClearAllPoints()
       PortalLibraryRaid:SetPoint("BOTTOMRIGHT", DungeonFrame, "BOTTOMRIGHT", adjustedX, adjustedY)
   end
end

-- MARK: Save Function on Close
local function OnPVEFrameClose()
   SavePortalLibraryRaidPosition()
end

-- Font Check and Change
local UserFont = "Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf"

local function LocaleFontCheck()
    if GetLocale() == "zhCN" then 
        UserFont = "Interface/AddOns/MDungeonTeleports/media/fonts/sarasa.ttf"
    elseif GetLocale() == "koKR" then 
        UserFont = "Interface/AddOns/MDungeonTeleports/media/fonts/wanted.ttf"
    else 
        UserFont = "Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf"
    end
end

-- MARK: Login Start Up
local function OnPlayerLogin()
    LocaleFontCheck()
    UpdatePortalLibRaidBackground()
    LoadPortalLibraryRaidPosition()
    UpdatePortalLibraryRaidUI()
    CompactModePortalLibraryRaid()
    ShiftDragToggleRL()
end

local loginFrame = CreateFrame("Frame")
loginFrame:RegisterEvent("PLAYER_LOGIN")
loginFrame:SetScript(
   "OnEvent",
   function(self, event)
       if event == "PLAYER_LOGIN" then
           OnPlayerLogin()
       end
   end
)

-- MARK: Tooltip Toggle
function ToggleTooltips()
   MDungeonTeleports.showTooltips = not MDungeonTeleports.showTooltips
end

-- MARK: Visibility Toggle
function PortalLibraryRaid_UpdateVisibility(show)
   local portalLibraryRaidFrame = _G["PortalLibraryRaid"]
   if portalLibraryRaidFrame then
       portalLibraryRaidFrame:SetShown(show)
   end
end

-- MARK: Portal Library Raid Frame
local PortalLibraryRaid = CreateFrame("Frame", "PortalLibraryRaid", PVEFrame)
PortalLibraryRaid:SetSize(124, 212)
PortalLibraryRaid:SetPoint("CENTER", PVEFrame, "CENTER", 860, -270)
PortalLibraryRaid:SetMovable(true)
PortalLibraryRaid:EnableMouse(true)
PortalLibraryRaid:RegisterForDrag("LeftButton")
PortalLibraryRaid:SetClampedToScreen(true)

PortalLibraryRaid.isBeingDragged = false

PortalLibraryRaid:SetScript(
   "OnDragStart",
   function(self)
       self.isBeingDragged = true
       self:StartMoving()
   end
)

PortalLibraryRaid:SetScript(
   "OnDragStop",
   function(self)
       if self.isBeingDragged then
           self:StopMovingOrSizing()
           SavePortalLibraryRaidPosition()
           self.isBeingDragged = false
           ReattachPortalLibraryRaid()
       end
   end
)

-- Portal Library Raid Background
local backgroundPortalLibRaid = PortalLibraryRaid:CreateTexture(nil, "Background")
backgroundPortalLibRaid:SetAllPoints(PortalLibraryRaid)
backgroundPortalLibRaid:SetTexture("Interface/AddOns/MDungeonTeleports/media/framepacks/frames/default_frames.blp")
backgroundPortalLibRaid:SetTexCoord(0.5, 0.621582, 0, 0.207031)
backgroundPortalLibRaid:SetVertexColor(1, 1, 1, 1)

-- MARK: Update Background Function
function UpdatePortalLibRaidBackground()
   local selectedTexture

   if MDungeonTeleports.CompactMode then
       selectedTexture = "Interface/Addons/MDungeonTeleports/media/framepacks/frames/borderless_frames.blp"
   else
       selectedTexture =
           MDungeonTeleports.selectedFramePack or
           "Interface/Addons/MDungeonTeleports/media/framepacks/frames/default_frames.blp"
   end

   backgroundPortalLibRaid:SetTexture(selectedTexture)
end

-- Portal Library Raid Title
local PortalLibraryRaidTitle = PortalLibraryRaid:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
PortalLibraryRaidTitle:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -10)
PortalLibraryRaidTitle:SetFont(UserFont, 13, "OUTLINE")
PortalLibraryRaidTitle:SetText(L["RAID_LIBRARY"])

-- Shadowlands Title
local titleShadowlands = PortalLibraryRaid:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
titleShadowlands:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -27)
local font, _, flags = titleShadowlands:GetFont()
titleShadowlands:SetFont(UserFont, 11, "OUTLINE")
titleShadowlands:SetTextColor(0.2, 0.8, 0.9)
titleShadowlands:SetText(L["EXP_SL"])

-- Dragonflight Title
local titleDragonflight = PortalLibraryRaid:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
titleDragonflight:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -87)
local font, _, flags = titleDragonflight:GetFont()
titleDragonflight:SetFont(UserFont, 11, "OUTLINE")
titleDragonflight:SetTextColor(0.2, 0.8, 0.9)
titleDragonflight:SetText(L["EXP_DF"])

-- The War Within Title
local titleTheWarWithin = PortalLibraryRaid:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
titleTheWarWithin:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -147)
local font, _, flags = titleTheWarWithin:GetFont()
titleTheWarWithin:SetFont(UserFont, 11, "OUTLINE")
titleTheWarWithin:SetTextColor(0.2, 0.8, 0.9)
titleTheWarWithin:SetText(L["EXP_TWW"])

-- MARK: Time Formatting
local function FormatCooldownTime(seconds)
   if seconds >= 3600 then
       local hours = math.floor(seconds / 3600)
       return string.format("%dh", hours)
   elseif seconds >= 60 then
       local minutes = math.floor(seconds / 60)
       return string.format("%dm", minutes)
   else
       return string.format("%ds", math.floor(seconds))
   end
end

-- -MARK: Cooldown Text Function
local function UpdateCooldownText(button, spellID)
   local cooldownFrame = button.cooldownText
   local cooldownOverlay = button.cooldownOverlay
   local spellCooldownInfo = C_Spell.GetSpellCooldown(spellID)

   if spellCooldownInfo then
       local startTime = spellCooldownInfo.startTime
       local duration = spellCooldownInfo.duration
       local isEnabled = spellCooldownInfo.isEnabled

       if startTime > 0 and duration > 0 and isEnabled then
           local remaining = max(0, (startTime + duration) - GetTime())

           -- Hide text and overlay if remaining time is 5 seconds or less
           if remaining > 5 then
               cooldownFrame:SetText(FormatCooldownTime(remaining))
               cooldownOverlay:Show()
           else
               cooldownFrame:SetText("")
               cooldownOverlay:Hide()
           end
       else
           cooldownFrame:SetText("")
           cooldownOverlay:Hide()
       end
   else
       cooldownFrame:SetText("")
       cooldownOverlay:Hide()
   end
end

-- MARK: Button Settings
local buttonSize = 32
local buttonSpacing = 5

local spellButtons = {}

-- MARK: Button Creation
local function CreateSpellButton(parent, data, rowOffset, horizontalOffset)
   local button = CreateFrame("Button", nil, parent, "SecureActionButtonTemplate")
   button:SetSize(buttonSize, buttonSize)
   button:SetPoint(
       "TOPLEFT",
       parent,
       "TOPLEFT",
       (data.index - 1) * (buttonSize + buttonSpacing) + 10 + (horizontalOffset or 0),
       rowOffset
   )

   button.data = data

   -- Texture for the button
   local buttonTexture = button:CreateTexture(nil, "ARTWORK")
   buttonTexture:SetAllPoints(button)
   buttonTexture:SetTexture(data.icon)

   -- Border texture
   local borderTexture = button:CreateTexture(nil, "OVERLAY")
   borderTexture:SetAllPoints(button)
   borderTexture:SetTexture("Interface\\AddOns\\MDungeonTeleports\\media\\ui\\ui_default\\button_border.blp")
   borderTexture:SetDrawLayer("OVERLAY", 2)
   button.borderTexture = borderTexture

   -- Cooldown texture
   local cooldownOverlay = button:CreateTexture(nil, "OVERLAY")
   cooldownOverlay:SetAllPoints(button)
   cooldownOverlay:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background")
   cooldownOverlay:SetVertexColor(0, 0, 0, 0.6)
   cooldownOverlay:Hide()
   button.cooldownOverlay = cooldownOverlay

   -- Button text
   local buttonText = button:CreateFontString(nil, "OVERLAY", "GameFontNormal")
   buttonText:SetPoint("TOP", button, "BOTTOM", 1, -2)
   local font, _, flags = buttonText:GetFont()
   buttonText:SetFont(UserFont, 11, "OUTLINE")
   buttonText:SetTextColor(1, 1, 1)
   buttonText:SetText(data.name)
   button.buttonText = buttonText

   -- Cooldown text
   local cooldownText = button:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
   cooldownText:SetPoint("CENTER", button, "CENTER", 1, 0)
   cooldownText:SetTextColor(1, 1, 1)
   cooldownText:SetFont(UserFont, 14, "OUTLINE")
   button.cooldownText = cooldownText

   -- Spell ID
   button:SetAttribute("type", "spell")
   button:SetAttribute("spell", data.spellID)

   -- Hover overlay
   local hoverOverlay = button:CreateTexture(nil, "HIGHLIGHT")
   hoverOverlay:SetAllPoints(button)
   hoverOverlay:SetTexture("Interface\\AddOns\\MDungeonTeleports\\media\\ui\\ui_default\\button_highlight.blp")
   hoverOverlay:Hide()
   button.hoverOverlay = hoverOverlay

   table.insert(spellButtons, button)

   -- Button texture update function
   local function UpdateButtonTexture()
       local UIPack

       if MDungeonTeleports.CompactMode then
           UIPack = "Interface/Addons/MDungeonTeleports/media/ui/ui_default/"
       else
           UIPack = MDungeonTeleports.selectedUIPack or "Interface/Addons/MDungeonTeleports/media/ui/ui_default/"
       end

       if IsSpellKnown(data.spellID) then
           buttonTexture:SetTexture(data.icon)
       elseif MDungeonTeleports.AltLocks then
           if type(AltLocks) == "table" then
               for _, lock in ipairs(AltLocks) do
                   if lock.spellID == data.spellID then
                       buttonTexture:SetTexture(lock.icon)
                       buttonTexture:SetAlpha(0.6)
                       buttonTexture:SetDesaturated(true)
                       return
                   end
               end
           end
           buttonTexture:SetTexture(UIPack .. "lock.blp")
           buttonTexture:SetAlpha(1)
           buttonTexture:SetDesaturated(false)
       else
           buttonTexture:SetTexture(UIPack .. "lock.blp")
           buttonTexture:SetAlpha(1)
           buttonTexture:SetDesaturated(false)
       end
   end

   button.UpdateButtonTexture = UpdateButtonTexture

   UpdateButtonTexture()

   -- Event handler
   local function OnEvent(self, event)
       if event == "SPELL_UPDATE_COOLDOWN" or event == "SPELLS_CHANGED" then
           UpdateButtonTexture()
           UpdateCooldownText(self, data.spellID)
       end
   end

   -- Tooltips and hover
   button:SetScript(
       "OnEnter",
       function(self)
           if MDungeonTeleports.showTooltips then
               GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
               GameTooltip:SetSpellByID(data.spellID)
               GameTooltip:Show()
           end
           hoverOverlay:Show()
       end
   )

   button:SetScript(
       "OnLeave",
       function(self)
           GameTooltip:Hide()
           hoverOverlay:Hide()
       end
   )

   -- Register events
   button:RegisterEvent("SPELL_UPDATE_COOLDOWN")
   button:RegisterEvent("SPELLS_CHANGED")
   button:RegisterForClicks("AnyUp", "AnyDown")
   button:SetScript("OnEvent", OnEvent)

   return button
end

-- MARK: Update UI Function
function UpdatePortalLibraryRaidUI()
   local UIPack

   if MDungeonTeleports.CompactMode then
       UIPack = "Interface/Addons/MDungeonTeleports/media/ui/ui_default/"
   else
       UIPack = MDungeonTeleports.selectedUIPack or "Interface/Addons/MDungeonTeleports/media/ui/ui_default/"
   end

   for _, btn in ipairs(spellButtons) do
       if btn.borderTexture then
           btn.borderTexture:SetTexture(UIPack .. "button_border.blp")
       end
       if btn.hoverOverlay then
           btn.hoverOverlay:SetTexture(UIPack .. "button_highlight.blp")
       end
       if btn.UpdateButtonTexture then
           btn.UpdateButtonTexture()
       end
   end
end

--MARK: Button Rows Setup
local rowOffset = -40
local row1HorizontalOffset = 0
local row2Offset = -100
local row2HorizontalOffset = 0
local row3Offset = -160
local row3HorizontalOffset = 0

-- MARK: Button Rows Setup
for i, data in ipairs(MDT_PLR_SL) do
   data.index = i
   data.row = 1
   CreateSpellButton(PortalLibraryRaid, data, rowOffset, row1HorizontalOffset)
end

for i, data in ipairs(MDT_PLR_DF) do
   data.index = i
   data.row = 2
   CreateSpellButton(PortalLibraryRaid, data, row2Offset, row2HorizontalOffset)
end

for i, data in ipairs(MDT_PLR_TWW) do
   data.index = i
   data.row = 3
   CreateSpellButton(PortalLibraryRaid, data, row3Offset, row3HorizontalOffset)
end

-- Compact Mode Start
function CompactModePortalLibraryRaid()
   if MDungeonTeleports.CompactMode == true then
       CompactModePortalLibraryRaidOn()
   else
       CompactModePortalLibraryRaidOff()
   end
end

-- MARK: Compact Mode Functions
function CompactModePortalLibraryRaidOn()
   PortalLibraryRaid:SetSize(116, 156)
   backgroundPortalLibRaid:SetTexCoord(0.5, 0.621582, 0, 0.207031)
   PortalLibraryRaidTitle:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -4)
   PortalLibraryRaidTitle:SetFont(UserFont, 11, "OUTLINE")

   titleShadowlands:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -15)
   titleDragonflight:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -61)
   titleTheWarWithin:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -107)

   titleShadowlands:SetFont(UserFont, 10, "OUTLINE")
   titleDragonflight:SetFont(UserFont, 10, "OUTLINE")
   titleTheWarWithin:SetFont(UserFont, 10, "OUTLINE")

   if spellButtons then
       for _, button in ipairs(spellButtons) do
           button:Hide()
       end
   end

   spellButtons = {}

   -- MARK: Button Rows Setup
   local rowOffset = -27
   local row1HorizontalOffset = -5
   local row2Offset = -73
   local row2HorizontalOffset = -5
   local row3Offset = -119
   local row3HorizontalOffset = -5

   for i, data in ipairs(MDT_PLR_SL) do
       data.index = i
       data.row = 1
       local button = CreateSpellButton(PortalLibraryRaid, data, rowOffset, row1HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for i, data in ipairs(MDT_PLR_DF) do
       data.index = i
       data.row = 2
       local button = CreateSpellButton(PortalLibraryRaid, data, row2Offset, row2HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for i, data in ipairs(MDT_PLR_TWW) do
       data.index = i
       data.row = 3
       local button = CreateSpellButton(PortalLibraryRaid, data, row3Offset, row3HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for _, button in ipairs(spellButtons) do
       local buttonText = button.buttonText
       if buttonText then
           buttonText:ClearAllPoints()
           buttonText:SetPoint("TOP", button, "BOTTOM", 1, 12)
           buttonText:SetFont(UserFont, 10, "OUTLINE")
       end

       local cooldownText = button.cooldownText
       if cooldownText then
           cooldownText:ClearAllPoints()
           cooldownText:SetPoint("CENTER", button, "CENTER", 0, 4)
           cooldownText:SetFont(UserFont, 12, "OUTLINE")
       end
   end
end

function CompactModePortalLibraryRaidOff()
   PortalLibraryRaid:SetSize(124, 212)
   backgroundPortalLibRaid:SetTexCoord(0.5, 0.621582, 0, 0.207031)
   PortalLibraryRaidTitle:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -10)
   PortalLibraryRaidTitle:SetFont(UserFont, 13, "OUTLINE")

   titleShadowlands:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -27)
   titleDragonflight:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -87)
   titleTheWarWithin:SetPoint("TOP", PortalLibraryRaid, "TOP", 0, -147)

   titleShadowlands:SetFont(UserFont, 11, "OUTLINE")
   titleDragonflight:SetFont(UserFont, 11, "OUTLINE")
   titleTheWarWithin:SetFont(UserFont, 11, "OUTLINE")

   if spellButtons then
       for _, button in ipairs(spellButtons) do
           button:Hide()
       end
   end

   spellButtons = {}

   -- MARK: Button Rows Setup
   local rowOffset = -40
   local row1HorizontalOffset = 0
   local row2Offset = -100
   local row2HorizontalOffset = 0
   local row3Offset = -160
   local row3HorizontalOffset = 0

   for i, data in ipairs(MDT_PLR_SL) do
       data.index = i
       data.row = 1
       local button = CreateSpellButton(PortalLibraryRaid, data, rowOffset, row1HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for i, data in ipairs(MDT_PLR_DF) do
       data.index = i
       data.row = 2
       local button = CreateSpellButton(PortalLibraryRaid, data, row2Offset, row2HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for i, data in ipairs(MDT_PLR_TWW) do
       data.index = i
       data.row = 3
       local button = CreateSpellButton(PortalLibraryRaid, data, row3Offset, row3HorizontalOffset)
       table.insert(spellButtons, button)
   end

   for _, button in ipairs(spellButtons) do
       local buttonText = button.buttonText
       if buttonText then
           buttonText:ClearAllPoints()
           buttonText:SetPoint("TOP", button, "BOTTOM", 1, -2)
           buttonText:SetFont(UserFont, 11, "OUTLINE")
       end

       local cooldownText = button.cooldownText
       if cooldownText then
           cooldownText:ClearAllPoints()
           cooldownText:SetPoint("CENTER", button, "CENTER", 1, 0)
           cooldownText:SetFont(UserFont, 14, "OUTLINE")
       end
   end
end

-- MARK: Shift Drag Toggle
function ShiftDragToggleRL()
    if MDungeonTeleports.ShiftDragToggle == true then
        PortalLibraryRaid:SetScript("OnDragStart", function(self)
            if IsShiftKeyDown() then
                self.isBeingDragged = true
                self:StartMoving()
            end
        end)
    else
        PortalLibraryRaid:SetScript("OnDragStart", function(self)
            self.isBeingDragged = true
            self:StartMoving()
        end)
    end
end

UpdatePortalLibraryRaidUI()