-- Initialize the addon
local addonName, addonTable = ...
local frame = CreateFrame("Frame")

-- Saved variables
SpellboundDB = SpellboundDB or {}
if SpellboundDB.soundOn == nil then
    SpellboundDB.soundOn = true 
end

-- Game state variables
local gameRunning = false
local gamePaused = false
local icons = {}
local revealedIcons = {}
local matchedIcons = {}
local startTime, elapsedTime = 0, 0
local playerName = UnitName("player")
local firstTimeOpen = true -- to help force grid creation on first showing
local difficultyButtons = {}
--local soundOn = {}

-- Table to set images for each race
local raceBackgrounds = {
    ["Human"] = "Interface\\AddOns\\Spellbound\\art\\human.tga",
    ["Orc"] = "Interface\\AddOns\\Spellbound\\art\\orc.tga",
    ["Dwarf"] = "Interface\\AddOns\\Spellbound\\art\\dwarf.tga",
    ["Night Elf"] = "Interface\\AddOns\\Spellbound\\art\\nightelf.tga",
    ["Undead"] = "Interface\\AddOns\\Spellbound\\art\\undead.tga",
    ["Tauren"] = "Interface\\AddOns\\Spellbound\\art\\tauren.tga",
    ["Gnome"] = "Interface\\AddOns\\Spellbound\\art\\gnome.tga",
    ["Troll"] = "Interface\\AddOns\\Spellbound\\art\\troll.tga",
    ["Blood Elf"] = "Interface\\AddOns\\Spellbound\\art\\bloodelf.tga",
    ["Draenei"] = "Interface\\AddOns\\Spellbound\\art\\draenei.tga",
    ["Worgen"] = "Interface\\AddOns\\Spellbound\\art\\worgen.tga",
    ["Goblin"] = "Interface\\AddOns\\Spellbound\\art\\goblin.tga",
    ["Pandaren"] = "Interface\\AddOns\\Spellbound\\art\\pandaren.tga",
    ["Nightborne"] = "Interface\\AddOns\\Spellbound\\art\\nightborne.tga",
    ["Highmountain Tauren"] = "Interface\\AddOns\\Spellbound\\art\\highmountaintauren.tga",
    ["Void Elf"] = "Interface\\AddOns\\Spellbound\\art\\voidelf.tga",
    ["Lightforged Draenei"] = "Interface\\AddOns\\Spellbound\\art\\lightforgeddraenei.tga",
    ["Zandalari Troll"] = "Interface\\AddOns\\Spellbound\\art\\zandalaritroll.tga",
    ["Kul Tiran"] = "Interface\\AddOns\\Spellbound\\art\\kultiran.tga",
    ["Dark Iron Dwarf"] = "Interface\\AddOns\\Spellbound\\art\\darkirondwarf.tga",
    ["Mag'har Orc"] = "Interface\\AddOns\\Spellbound\\art\\magharorc.tga",
    ["Mechagnome"] = "Interface\\AddOns\\Spellbound\\art\\mechagnome.tga",
    ["Vulpera"] = "Interface\\AddOns\\Spellbound\\art\\vulpera.tga",
    ["Dracthyr"] = "Interface\\AddOns\\Spellbound\\art\\dracthyr.tga",
    ["Earthen"] = "Interface\\AddOns\\Spellbound\\art\\earthen.tga"
}

-- Variables to store the current difficulty and scoreboards
local currentDifficulty = "4x4"
local scoreboards = {
    ["4x4"] = {},
    ["6x5"] = {},
    ["8x5"] = {}
}

-- Initialize scoreboards when the addon is loaded
local function OnEvent(self, event, ...)
    if event == "ADDON_LOADED" then
        local addon = ...
        if addon == addonName then
            -- Initialize saved variables
            if not SpellboundDB.scores then
                SpellboundDB.scores = {
                    ["4x4"] = {},
                    ["6x5"] = {},
                    ["8x5"] = {}
                }
            end
            scoreboards = SpellboundDB.scores
         --   print("Spellbound loaded!")
        end
    -- elseif event == "PLAYER_LOGIN" then
        -- print("Welcome to Spellbound!")
    end
end

-- Desaturate the grid
local function DesaturateIcons(desaturate)
    for i = 1, 40 do -- Maximum possible buttons for the largest grid 
        local button = _G["IconButton"..i]
        if button then
            local texture = button:GetNormalTexture()
            if texture then
                texture:SetDesaturated(desaturate)
            end
        end
    end
end

-- Return desaturation to only matched icons
local function ReapplyMatchedIconsDesaturation()
    for button, _ in pairs(matchedIcons) do
        local texture = button:GetNormalTexture()
        if texture then
            texture:SetDesaturated(true)
        end
    end
end

-- Get the players race and set the background image 
local function GetPlayerRace()
    local race = UnitRace("player")
    return race
end

-- Set the background based on players race
local function SetFrameBackground(frame)
    local playerRace = GetPlayerRace()
    local backgroundImage = raceBackgrounds[playerRace]

    if backgroundImage then
        frame:SetBackdrop({
            bgFile = backgroundImage,
            edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", 
            tile = false,
            tileSize = 0,
            edgeSize = 10,
            insets = { left = 1, right = 1, top = 1, bottom = 1 }
        })
    else
        print("No background image found for race: " .. playerRace)
    end
end

local playerRace = GetPlayerRace()
-- print("Player race is: " .. playerRace)

-- Get the player's current specialization icon
local function GetPlayerSpecIcon()
    local specIndex = GetSpecialization()
    if specIndex then
        local _, _, _, icon = GetSpecializationInfo(specIndex)
        return icon
    end
    return "Interface\\Icons\\INV_Misc_QuestionMark" -- Default to question mark if no spec found
end

-- Get the player's spec icon to exclude it
local function GetPlayerSpecIcon()
    local currentSpec = GetSpecialization()
    if currentSpec then
        local _, _, _, icon = GetSpecializationInfo(currentSpec)
        return icon
    end
end

-- Get icons from the spellbook
local function GetSpellbookIcons(specIcon)
    local icons = {}

    for tab = 1, C_SpellBook.GetNumSpellBookSkillLines() do
        local name, _, offset, numSpells, _, spec = C_SpellBook.GetSpellBookSkillLineInfo(tab)
        if spec then -- Check if the tab is for the player's spec
            for i = offset + 1, offset + numSpells do
                local spellType, spellID = GetSpellBookItemInfo(i, "player")
                if spellType == "SPELL" then
                    local icon = GetSpellBookItemTexture(i, "player")
                    if icon and icon ~= specIcon then
                        table.insert(icons, icon)
                    end
                end
            end
        end
    end

    return icons
end

-- Get icons from the talent tree
local function GetTalentTreeIcons(specIcon)
    local icons = {}

    for tier = 1, MAX_TALENT_TIERS do
        for column = 1, NUM_TALENT_COLUMNS do
            local talentID, name, icon, selected, available, spellID = GetTalentInfo(tier, column, 1)
            if icon and icon ~= specIcon then
                table.insert(icons, icon)
            end
        end
    end

    return icons
end

-- Consolidated function to get all relevant icons from spellbook and talent tree
local function GetIcons()
    local specIcon = GetPlayerSpecIcon()
    local spellbookIcons = GetSpellbookIcons(specIcon)
    local talentTreeIcons = GetTalentTreeIcons(specIcon)
    local icons = {}

    for _, icon in ipairs(spellbookIcons) do
        table.insert(icons, icon)
    end
    for _, icon in ipairs(talentTreeIcons) do
        table.insert(icons, icon)
    end

    return icons
end

-- Shuffle icons
local function ShuffleIcons(iconList)
    local shuffled = {}
    for i = #iconList, 1, -1 do
        local rand = math.random(i)
        shuffled[i] = iconList[rand]
        table.remove(iconList, rand)
    end
    return shuffled
end

-- Update the timer
local function UpdateTimer()
    if gameRunning and not gamePaused then
        elapsedTime = GetTime() - startTime
        local minutes = math.floor(elapsedTime / 60)
        local seconds = math.floor(elapsedTime % 60)
        timerText:SetText(string.format("Time: %02d:%02d", minutes, seconds))
    end
end

-- Update the scoreboard display based on the current difficulty
local function UpdateScoreDisplay()
    local scores = scoreboards[currentDifficulty]
    table.sort(scores, function(a, b) return a.time < b.time end)
    
    while #scores > 10 do  -- Trim the scores list to only keep the top 10 times
        table.remove(scores)
    end

	local scoreTextStr = ("")
    for i = 1, math.min(10, #scores) do
        local score = scores[i]
        local minutes = math.floor(score.time / 60)
        local seconds = math.floor(score.time % 60)
        --scoreTextStr = scoreTextStr .. string.format("%-02d %10s %15s\n", i, string.format("%-02d:%-02d", minutes, seconds), score.player)
		scoreTextStr = scoreTextStr .. string.format("%-6s %20s\n", string.format("%2d:%02d", minutes, seconds), score.player)
    end
    scoreText:SetText(scoreTextStr)
end

-- Create the End Game Animation
local function ApplyEndGameEffects()
    C_Timer.After(1, function()
        for i = 1, #icons do
            local button = _G["IconButton" .. i]
            if button then
                ActionButton_ShowOverlayGlow(button) -- Add glow effect
                
                -- Create a flash animation
                local flash = button:CreateAnimationGroup()
                local fadeIn = flash:CreateAnimation("Alpha")
                fadeIn:SetFromAlpha(0.3)
                fadeIn:SetToAlpha(1)
                fadeIn:SetDuration(0.5)
                fadeIn:SetSmoothing("IN")
                
                local fadeOut = flash:CreateAnimation("Alpha")
                fadeOut:SetFromAlpha(1)
                fadeOut:SetToAlpha(0.3)
                fadeOut:SetDuration(0.5)
                fadeOut:SetSmoothing("OUT")
                fadeOut:SetStartDelay(0.5)

                -- Limit the fade effect to X repetitions
                local count = 0
                flash:SetScript("OnLoop", function(self, loopState)
                    count = count + 1
                    if count >= 3 then
                        self:Stop()
                    end
                end)
                
                flash:SetLooping("REPEAT")
                flash:Play()
            end
        end
    end)
end

-- Register events
frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("PLAYER_LOGOUT") 
frame:SetScript("OnEvent", OnEvent)

-- Create the main frame
local spellboundFrame = CreateFrame("Frame", "SpellboundFrame", UIParent, "BackdropTemplate")
spellboundFrame:SetSize(800, 400)
spellboundFrame:SetPoint("CENTER")
spellboundFrame:SetMovable(true)
spellboundFrame:EnableMouse(true)
spellboundFrame:SetClampedToScreen(true)
spellboundFrame:SetFrameStrata("HIGH")

-- Create Frame to display messages
local messageFrame = CreateFrame("MessageFrame", "MessageFrame", UIParent)
messageFrame:SetSize(800, 40)
messageFrame:SetPoint("CENTER", SpellboundFrame, "TOP", 0, 10)
--messageFrame:SetFont("Fonts\\FRIZQT__.TTF", 20, "OUTLINE")
messageFrame:SetFont("Fonts\\FRIZQT__.TTF", 20, "THICKOUTLINE")
messageFrame:SetInsertMode("TOP")
messageFrame:SetFrameStrata("HIGH")
messageFrame:SetTimeVisible(3)
messageFrame:SetJustifyH("CENTER") 
messageFrame:SetJustifyV("MIDDLE") 

-- Create and set background texture
local bgTexture = messageFrame:CreateTexture(nil, "BACKGROUND")
bgTexture:SetColorTexture(0, 0, 0, 0.75)
bgTexture:SetAllPoints(messageFrame)
messageFrame.background = bgTexture

-- Hide the frame initially
messageFrame:Hide()

-- Message queue
local messageQueue = {}
local isDisplaying = false

-- Set the backdrop with the background image and adjusted insets
SetFrameBackground(spellboundFrame)

-- Create a title bar for dragging
local titleBar = CreateFrame("Frame", nil, spellboundFrame, "BackdropTemplate")
titleBar:SetSize(spellboundFrame:GetWidth() -2, 32)
titleBar:SetPoint("TOP", 0, 0)
titleBar:EnableMouse(true)
titleBar:RegisterForDrag("LeftButton")
titleBar:SetScript("OnDragStart", function() spellboundFrame:StartMoving() end)
titleBar:SetScript("OnDragStop", function() spellboundFrame:StopMovingOrSizing() end)
titleBar:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8X8", 
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", 
    tile = true,
    tileSize = 32,
    edgeSize = 10,
    insets = { left = 3, right = 3, top = 1, bottom = 1 } 
})
titleBar:SetBackdropColor(0, 0, 0, 0.9)

-- Title text
titleBar.title = titleBar:CreateFontString(nil, "OVERLAY")
titleBar.title:SetFontObject("GameFontNormalLarge")
titleBar.title:SetTextColor(1, 1, 0)
titleBar.title:SetPoint("CENTER", titleBar, "CENTER", 0, 0)
titleBar.title:SetText("Spellbound")

-- Create a close button
local closeButton = CreateFrame("Button", nil, spellboundFrame, "UIPanelCloseButton")
closeButton:SetPoint("TOPRIGHT", spellboundFrame, "TOPRIGHT", -5, -5)

-- Show the frame and make it closable with the "Esc" key
table.insert(UISpecialFrames, spellboundFrame:GetName())
tleBar = CreateFrame("Frame", nil, spellboundFrame)

-- Cleanup function to reset variables
local function Cleanup()
    gameRunning = false
    gamePaused = false
    icons = {}
    revealedIcons = {}
    startTime, elapsedTime = 0, 0
    -- print("Spellbound cleanup completed.")
end

-- Create a timer display
local timerFrame = CreateFrame("Frame", nil, spellboundFrame, "BackdropTemplate")
timerFrame:SetSize(200, 50)
timerFrame:SetPoint("TOPRIGHT", -40, -40)
timerFrame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true, tileSize = 32, edgeSize = 32,
    insets = { left = 8, right = 8, top = 8, bottom = 8 }
})
timerText = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") -- Ensure timerText is global
timerText:SetPoint("CENTER")
timerText:SetText("Time: 00:00")

-- Create a score display
local scoreFrame = CreateFrame("Frame", nil, spellboundFrame, "BackdropTemplate")
scoreFrame:SetSize(200, 150)
scoreFrame:SetPoint("TOPRIGHT", -40, -90)
scoreFrame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true, tileSize = 32, edgeSize = 32,
    insets = { left = 8, right = 8, top = 8, bottom = 8 }
})
scoreText = scoreFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
scoreText:SetPoint("TOP", 0, -15)
scoreText:SetJustifyH("LEFT")

-- Function to Display the next message in queue
local function DisplayNextMessage()
    if #messageQueue == 0 then
        isDisplaying = false
        return
    end

    isDisplaying = true
    local messageData = table.remove(messageQueue, 1)
    local message, r, g, b, fontSize = unpack(messageData)

    local fontType = ChatTypeInfo["RAID_WARNING"]
    fontType.r = r or 1.0 -- Default to white 
    fontType.g = g or 1.0
    fontType.b = b or 1.0

    messageFrame:SetFont("Fonts\\FRIZQT__.TTF", fontSize or 20, "THICKOUTLINE") 
    messageFrame:SetAlpha(1) -- Reset the alpha value to full opacity
    messageFrame:Show()  -- Show the frame and its background
    messageFrame.background:Show()

    -- Display the message
    messageFrame:AddMessage(message, fontType.r, fontType.g, fontType.b, 1.0)

    -- Hide the frame after 3 seconds and fade out over 1 second
    C_Timer.After(3, function()
        UIFrameFadeOut(messageFrame, 1, messageFrame:GetAlpha(), 0) -- Fade out over 1 second
        C_Timer.After(1, function() -- Hide the frame after the fade out
            messageFrame:Hide()
            messageFrame.background:Hide()
            DisplayNextMessage() -- Display the next message in the queue
        end)
    end)
end

-- Function to Display the message
local function DisplayMessage(message, r, g, b, fontSize)
    table.insert(messageQueue, {message, r, g, b, fontSize})
    if not isDisplaying then
        DisplayNextMessage()
    end
end

-- Check if the game has ended
local function CheckGameEnd()
    local allMatched = true
    local gridSize = (currentDifficulty == "4x4" and 16) or (currentDifficulty == "6x5" and 30) or 40
    for i = 1, gridSize do
        local button = _G["IconButton"..i]
        if button and not button.revealed then
            allMatched = false
            break
        end
    end
    if allMatched then
        gameRunning = false
        frame:SetScript("OnUpdate", nil)
		
		-- Save the rounded elapsed time to the current scoreboard
		-- local roundedElapsedTime = math.floor(elapsedTime + 0.5)
		local roundedElapsedTime = math.floor(elapsedTime * 10 + 0.5) / 10
		table.insert(scoreboards[currentDifficulty], {time = roundedElapsedTime, player = playerName})
        UpdateScoreDisplay() -- Save and display scores when the game ends
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\win.ogg", "Master") -- play winning sound
		end
		
		-- Change the start button to "Well Done!" and make it unclickable
        startPauseButton:SetText("Well Done!")
		local font, size, flags = startPauseButton:GetFontString():GetFont()
		startPauseButton:GetFontString():SetFont(font, size + 6, "THICKOUTLINE")
		startPauseButton:GetFontString():SetTextColor(1, 0.84, 0) 
        startPauseButton:Disable()
		ApplyEndGameEffects()
		print("|cff00ff00\nSpellbound - WELL DONE!|r")
		DisplayMessage("WELL DONE !", 0.0, 1.0, 0.0, 36)
    end
end

-- Create the grid
local function CreateIconGrid()
    -- Clear existing buttons
    for i = 1, 40 do -- Maximum possible buttons for the largest grid 
        local button = _G["IconButton"..i]
        if button then
            button:Hide()
            button:SetParent(nil)
            _G["IconButton"..i] = nil
        end
    end
    
    collectgarbage("collect")

    local CollectedIcons = GetIcons()
	if not CollectedIcons or #CollectedIcons == 0 then
        print("Spellbound: no icons available—aborting grid creation.")
        return
    end

    local selectedIcons = {}
    local gridWidth, gridHeight, numPairs, startPointX, startPointY

    if currentDifficulty == "4x4" then
        gridWidth, gridHeight, numPairs, startPointX, startPointY = 4, 4, 8, 140, -70 
    elseif currentDifficulty == "6x5" then
        gridWidth, gridHeight, numPairs, startPointX, startPointY = 6, 5, 15, 80, -40
    elseif currentDifficulty == "8x5" then
        gridWidth, gridHeight, numPairs, startPointX, startPointY = 8, 5, 20, 10, -40
    end

    -- Ensure we have enough icons to create pairs
    for i = 1, numPairs do
        local icon = CollectedIcons[(i - 1) % #CollectedIcons + 1]
        if icon then
            table.insert(selectedIcons, icon)
            table.insert(selectedIcons, icon) -- Add each icon twice
        else
            -- print("Error: Not enough icons available to create pairs.")
            return
        end
    end

    icons = ShuffleIcons(selectedIcons)
    local iconSize = 64 -- Twice the normal size of action bar icons (32x32)
    local defaultIcon = GetPlayerSpecIcon()

    -- Create buttons and check for matches
    for i = 1, gridWidth * gridHeight do
        local button = CreateFrame("Button", "IconButton"..i, spellboundFrame, "UIPanelButtonTemplate")
        button:SetSize(iconSize, iconSize)
        button:SetPoint("TOPLEFT", startPointX + ((i-1) % gridWidth) * (iconSize + 5), startPointY - math.floor((i-1) / gridWidth) * (iconSize + 5))
        button:SetNormalTexture("Interface\\Icons\\INV_Misc_QuestionMark") -- Default icon
        button:SetScript("OnClick", function(self)
            if gameRunning and not gamePaused then
                if not self.revealed and #revealedIcons < 2 then
                    if self.icon then
                        self:SetNormalTexture(self.icon)
						if SpellboundDB.soundOn then
							PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\flip.ogg", "Master")
                        end
						ActionButton_ShowOverlayGlow(self) -- Add glow effect
                    else
                       -- print("Error: Icon is nil for button "..i)
                    end
                    self.revealed = true
                    table.insert(revealedIcons, self)
                    -- Check for matches
                    if #revealedIcons == 2 then
                        if revealedIcons[1].icon and revealedIcons[2].icon and revealedIcons[1].icon == revealedIcons[2].icon then
                            -- Match found
                            for _, btn in ipairs(revealedIcons) do
                                local texture = btn:GetNormalTexture()
                                if texture then
                                    ActionButton_ShowOverlayGlow(self) -- Add glow effect
                                    texture:SetDesaturated(true)
									matchedIcons[btn] = true  -- Mark this button as matched for resaturating after resume
                                end
								if SpellboundDB.soundOn then
									PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\match3.ogg", "Master")
								end
								C_Timer.After(0.3, function()
                                    ActionButton_HideOverlayGlow(btn) -- Remove glow effect
                                end)
                            end
                            revealedIcons = {}
                            CheckGameEnd()
                        else
                            -- No match, hide icons again after a short delay
                            C_Timer.After(1, function()
                                for _, btn in ipairs(revealedIcons) do
                                    if btn.icon then
                                        local defaultIcon = GetPlayerSpecIcon() -- Fix error when returning to spec icon after failed match
                                        btn:SetNormalTexture(defaultIcon)
                                        ActionButton_HideOverlayGlow(btn) -- Remove glow effect
										if SpellboundDB.soundOn then
											PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\nomatch.ogg", "Master")
										end
                                        C_Timer.After(0.2, function()
											if SpellboundDB.soundOn then
												PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\flip.ogg", "Master")
											end
                                            C_Timer.After(0.1, function()
												if SpellboundDB.soundOn then
													PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\flip.ogg", "Master")
												end
                                            end)
                                        end)
                                    else
                                      --  print("Error: Icon is nil for button "..btn:GetName())
                                    end
                                    btn.revealed = false
                                end
                                revealedIcons = {}
                            end)
                        end
                    end
                end
            end
        end)
        button.icon = icons[i]
        button.revealed = false
        if button.icon then
            button:SetNormalTexture("Interface\\Icons\\INV_Misc_QuestionMark") -- Reset to default icon
        else
           -- print("Error: Icon is nil for button "..i)
        end
    end
    collectgarbage("collect")
end

CreateIconGrid()

-- Create a "Start/Pause/Resume" button
startPauseButton = CreateFrame("Button", "StartPauseButton", spellboundFrame, "UIPanelButtonTemplate") -- Ensure startPauseButton is global
startPauseButton:SetSize(200, 30)
startPauseButton:SetPoint("BOTTOMRIGHT", -40, 40)
startPauseButton:SetText("Start")
startPauseButton:SetScript("OnClick", function()
    if not gameRunning then
        -- Start the game
        gameRunning = true
        gamePaused = false
        startTime = GetTime()
		print("|cff00ff00\nSpellbound Game Started - GOOD LUCK!|r")
		DisplayMessage("Good Luck", 0.0, 1.0, 0.0, 32)
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\start.ogg", "Master")
		end
        startPauseButton:SetText("Pause")
        -- Disable difficulty buttons
        for _, button in ipairs(difficultyButtons) do
            button:Disable()
        end
        -- Update icons to player's spec icon
        local defaultIcon = GetPlayerSpecIcon()
        for i = 1, 40 do
            local button = _G["IconButton"..i]
            if button then
                button:SetNormalTexture(defaultIcon)
            end
        end
        -- Start timer 
        frame:SetScript("OnUpdate", UpdateTimer)
    elseif gamePaused then
        -- Resume the game
        gamePaused = false
		DesaturateIcons(false)
		ReapplyMatchedIconsDesaturation()
        startPauseButton:SetText("Pause")
        startTime = GetTime() - elapsedTime
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\resume.ogg", "Master")
		end
		print("|cff00ff00\nSpellbound RESUMED!|r")
		DisplayMessage("SpellBound Resumed", 0.0, 1.0, 0.0, 32)
	else
        -- Pause the game
        gamePaused = true
		DesaturateIcons(true)
        startPauseButton:SetText("Resume")
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\pause.ogg", "Master")
		end
		print("|cFFFF0000\nSpellbound PAUSED!|r")
		DisplayMessage("SpellBound PAUSED !", 1.0, 0.0, 0.0, 32)
    end
    UpdateScoreDisplay() 
end)

-- Create a "New Game" button
local newGameButton = CreateFrame("Button", "NewGameButton", StartPauseButton, "UIPanelButtonTemplate")
newGameButton:SetSize(200, 30)
newGameButton:SetPoint("BOTTOM", 0, 40)
newGameButton:SetText("New Game")
newGameButton:SetScript("OnClick", function()
	if not gameRunning then
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\newgame.ogg", "Master")
		end
	else
		if SpellboundDB.soundOn then
			PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\nomatch.ogg", "Master")
			C_Timer.After(1, function()
				PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\newgame.ogg", "Master")
			end)
		end
	end
	gameRunning = false
	gamePaused = false
	startPauseButton:SetText("Start")
	startPauseButton:Enable() -- Re-enable the button
	local fontString = startPauseButton:GetFontString()
	fontString:SetFont(GameFontNormal:GetFont()) -- Reset to default font
	timerText:SetText("Time: 00:00")
	elapsedTime = 0
	CreateIconGrid() -- Recreate the icon grid with new icons
	-- Enable difficulty buttons
	for _, button in ipairs(difficultyButtons) do
		button:Enable()
	end
	DisplayMessage("New Game - Icons Refreshed", 0.0, 1.0, 0.0, 32)
end)

-- Create the difficulty buttons
local function CreateDifficultyButtons()
    local difficulties = {"4x4", "6x5", "8x5"}
    for i, difficulty in ipairs(difficulties) do
        local button = CreateFrame("Button", "DifficultyButton"..i, NewGameButton, "UIPanelButtonTemplate")
        button:SetSize(60, 30)
        button:SetPoint("BOTTOM", -70 + (i-1) * 70, 40)
        button:SetText(difficulty)
		button:SetScript("OnClick", function()
            if not gameRunning and not gamePaused then
				if SpellboundDB.soundOn then
					PlaySoundFile("Interface\\AddOns\\Spellbound\\sounds\\click.ogg", "Master")
				end
                currentDifficulty = difficulty
                CreateIconGrid()
                UpdateScoreDisplay()
            end
        end)
        table.insert(difficultyButtons, button)
    end
end

CreateDifficultyButtons()

-- Create the About button
local aboutButton = CreateFrame("Button", "AboutButton", spellboundFrame, "UIPanelButtonTemplate")
aboutButton:SetSize(25, 25) 
aboutButton:SetPoint("BOTTOMRIGHT", spellboundFrame, "BOTTOMRIGHT", -42, 10) 
aboutButton:SetText("?")

-- Create the about window frame
local aboutWindow = CreateFrame("Frame", "AboutWindow", UIParent)
aboutWindow:SetSize(600, 300) 
aboutWindow:SetPoint("CENTER", UIParent, "CENTER", 0, 0) 
aboutWindow:SetFrameStrata("DIALOG")
aboutWindow:Hide() 

-- Enable mouse interaction and make the window movable
aboutWindow:EnableMouse(true)
aboutWindow:SetMovable(true)
aboutWindow:RegisterForDrag("LeftButton")
aboutWindow:SetScript("OnDragStart", aboutWindow.StartMoving)
aboutWindow:SetScript("OnDragStop", aboutWindow.StopMovingOrSizing)


-- Set the background 
local bgTexture = aboutWindow:CreateTexture(nil, "BACKGROUND")
bgTexture:SetColorTexture(0, 0, 0, 0.9)
bgTexture:SetAllPoints(aboutWindow)
aboutWindow.background = bgTexture

-- About window title
local title = aboutWindow:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
title:SetPoint("TOP", aboutWindow, "TOP", 0, -10)
title:SetText("About SpellBound")

-- About content 
local content = aboutWindow:CreateFontString(nil, "OVERLAY", "GameFontNormal")
content:SetPoint("TOPLEFT", aboutWindow, "TOPLEFT", 10, -50)
content:SetPoint("BOTTOMRIGHT", aboutWindow, "BOTTOMRIGHT", -10, 10)
content:SetJustifyH("LEFT")
content:SetJustifyV("TOP")
content:SetText("\n\nSpellBlound Is a Memory Matching Game\n\n" ..
				"    - The Theme is based on your Character's Race and Specillization\n" ..
				"    - The Icons are selected from you Spellbook\n" ..
				"    - The game will PAUSE any time the window is closed|n" ..
				"    - Countdows PAUSE the game and CLOSE the window\n" ..
				"\n\n\n" ..
				"Slash Commands\n\n" ..
				"    |c00FFFFFF|c0000FFFF/sb or /spellbound :|rOpens|Closes the game window\n" ..
				"    |c0000FFFF/sb resetscores :|rResets the scores\n" ..
				"    |c0000FFFF/sb resetall :|rResets the entire game|r" ..
				"\n\n\n\n" ..
				"|c000080FFMade By Kilrah"
				)

local closeButton = CreateFrame("Button", nil, aboutWindow, "UIPanelCloseButton")
closeButton:SetPoint("TOPRIGHT", aboutWindow, "TOPRIGHT")

-- Function to toggle the about window
local function ToggleAboutWindow()
    if aboutWindow:IsShown() then
        aboutWindow:Hide()
    else
        aboutWindow:Show()
        aboutWindow:SetFrameLevel(aboutWindow:GetFrameLevel() + 10) -- Ensure it is in focus
    end
end

-- Set the close button script
closeButton:SetScript("OnClick", function()
    aboutWindow:Hide()
end)

aboutButton:SetScript("OnClick", ToggleAboutWindow)
table.insert(UISpecialFrames, "AboutWindow")

-- Button click handler to toggle the window
aboutButton:SetScript("OnClick", function()
    if aboutWindow:IsShown() then
        aboutWindow:Hide()
    else
        aboutWindow:Show()
    end
end)

-- Initialize the sound button state
local function InitializeSoundToggle()
	local soundOn = SpellboundDB and SpellboundDB.soundOn
    if soundOn then
        soundToggle:SetText("On")
    else
        soundToggle:SetText("Off")
    end
end

-- Register the ADDON_LOADED event for sound button
local frame = CreateFrame("Frame")
frame:RegisterEvent("ADDON_LOADED")
frame:SetScript("OnEvent", function(self, event, addonName)
    if addonName == "Spellbound" then
		
        -- Create sound label
        local soundLabel = StartPauseButton:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        soundLabel:SetPoint("TOPRIGHT", -140, -43)
        soundLabel:SetText("Sound is")
		
		local bgTexture = StartPauseButton:CreateTexture(nil, "BACKGROUND")
		bgTexture:SetColorTexture(0, 0, 0, 0.80) 
		bgTexture:SetPoint("TOPLEFT", soundLabel, "TOPLEFT", -5, 5) 
		bgTexture:SetPoint("BOTTOMRIGHT", soundLabel, "BOTTOMRIGHT", 5, -5) 

		-- Ensure the background is behind the text
		soundLabel:SetDrawLayer("OVERLAY")
		
        -- Create sound on/off button
        soundToggle = CreateFrame("Button", "SoundToggleButton", StartPauseButton, "UIPanelButtonTemplate")
        soundToggle:SetSize(30, 25)
        soundToggle:SetPoint("LEFT", soundLabel, "RIGHT", 7, 2)

        -- Initialize the sound button state
        InitializeSoundToggle()

        -- Swap text on sound button
        soundToggle:SetScript("OnClick", function(self)
            if soundToggle:GetText() == "On" then 
                soundToggle:SetText("Off")
                SpellboundDB.soundOn = false
            else
                soundToggle:SetText("On")
                SpellboundDB.soundOn = true
            end
        end)
    end
end)

-- Force create the grid when frame shown for first time
spellboundFrame:SetScript("OnShow", function()
    if firstTimeOpen then
        CreateIconGrid()
        firstTimeOpen = false
    end
    InitializeSoundToggle() -- Ensure the sound toggle is initialized when the frame is shown
end)

--Close the game window
local function CloseGameWindow()
    if SpellboundFrame:IsShown() or AboutWindow:IsShown() then
        SpellboundFrame:Hide()
		AboutWindow:Hide()
	    -- Pause the game when the frame is closed
        if gameRunning then
            gamePaused = true
            startPauseButton:SetText("Resume")
        end
    end
end

-- Watch for entering combat
local function OnEvent(self, event, ...)
    if event == "PLAYER_REGEN_DISABLED" then
        if spellboundFrame:IsShown() then
            print("|cFFFF0000\nYou Enter Combat - Spellbound Pause & Closed|r")
			DisplayMessage("You Enter Combat SpellBound Paused & Closed", 1.0, .0, 0.0, 25)
            CloseGameWindow()
        end
    end
end

-- Watch for DBM Countdown
if DBM then
    DBM:RegisterCallback("DBM_TimerStart", function(event, timerId, timerType, timerText, timerTime, ...)
        if spellboundFrame:IsShown() then 
            C_Timer.After(1, function()
                print("|cFFFF0000\nDBM Countdown Started - Spellbound Pause & Closed|r")
				DisplayMessage("DBM Countdown - SpellBound Paused & Closed", 1.0, .0, 0.0, 25)
                CloseGameWindow()
            end)
        end
    end)
end

-- watch for BigWigs countdown
if BigWigsLoader then
    BigWigsLoader.RegisterMessage("Spellbound", "BigWigs_StartBar", function(event, module, key, text, time, icon, ...)
        if spellboundFrame:IsShown() then 
            C_Timer.After(1, function()
                print("|cFFFF0000\nBigWigs Countdown Started - Spellbound Pause & Closed|r")
				DisplayMessage("BigWigs Countdown - SpellBound Paused & Closed", 1.0, .0, 0.0, 25)
                CloseGameWindow()
            end)
        end
    end)
end

-- Watch for WoW Countdown
local frame = CreateFrame("Frame")
frame:RegisterEvent("START_TIMER")
frame:SetScript("OnEvent", function(self, event, ...)
    local timerType, timeRemaining = ...
    if spellboundFrame:IsShown() then
        C_Timer.After(1, function()
			print("|cFFFF0000\nCountdown Started - Spellbound Pause & Closed|r")
			DisplayMessage("Countdown - SpellBound Paused & Closed", 1.0, .0, 0.0, 25)			
			CloseGameWindow()
        end)
    end
end)

-- Create a frame to listen for events
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
eventFrame:SetScript("OnEvent", OnEvent)

-- Pause the game when the frame is closed
spellboundFrame:SetScript("OnHide", function()
    if gameRunning then
        gamePaused = true
        startPauseButton:SetText("Resume")
        print("|cFFFF0000\nGame Window Closed - Spellbound PAUSED!|r")
    end
end)

-- --  test Slash commands
-- SLASH_SBWINTEST1 = "/sbwintest" -- test win animation
-- SlashCmdList["SBWINTEST"] = function()
    -- ApplyEndGameEffects()
-- end

-- SLASH_SBTIMERTEST1 = "/sbtt"  -- test countdown timer
-- SlashCmdList["SBTIMERTEST"] = function(msg)
    -- C_Timer.After(1, function()
        -- local timerType = 1 -- Simulate a countdown timer type
        -- local timeRemaining = 10 -- Simulate the time remaining
        -- local totalTime = 5 -- Simulate the total time
        -- frame:GetScript("OnEvent")(frame, "START_TIMER", timerType, timeRemaining, totalTime)
    -- end)
    -- print("Simulated countdown.")
-- end

local helpMessage = "|c0000FF00\nSpellBound Help:|r\n" ..
							"|c0000FFFF/sb or /spellbound :|r Opens|Closes the game window\n" ..
							"|c0000FFFF/sb resetscores :|r Resets the scores\n" ..
							"|c0000FFFF/sb resetall :|r Resets the entire game\n" ..
							"|c0000FFFF/sb about :|r Show info about SpellBound"


-- Main slash commands
SLASH_SPELLBOUND1 = "/spellbound" -- Show/Hide game
SLASH_SPELLBOUND2 = "/sb" -- Show/Hide game

SlashCmdList["SPELLBOUND"] = function(msg)
    local command = msg:lower()
    
	if command == "help" then
		print(helpMessage)

	elseif command == "resetscores" then
        -- Reset all scores
        SpellboundDB.scores = {
            ["4x4"] = {},
            ["6x5"] = {},
            ["8x5"] = {}
        }
        scoreboards = SpellboundDB.scores
        UpdateScoreDisplay()
        print("All scores have been reset.")
        DisplayMessage("All Scores Have Been Reset", 1.0, 0.0, 0.0, 32)
    elseif command == "resetall" then
        -- Reset the entire SpellboundDB
        SpellboundDB = {
            soundOn = true, -- Default value
            scores = {
                ["4x4"] = {},
                ["6x5"] = {},
                ["8x5"] = {}
            }
        }
        scoreboards = SpellboundDB.scores
        UpdateScoreDisplay()
        print("Spellbound has been reset.")
        DisplayMessage("SpellBound Has Been Reset", 1.0, 0.0, 0.0, 32)
	elseif command == "about" then
		if AboutWindow:IsShown() then 
			AboutWindow:Hide()
		else 
			AboutWindow:Show()
		end
	else
        -- Check for empty command to toggle the window
        if command == "" then
            if spellboundFrame:IsShown() then
                spellboundFrame:Hide()
                print("|cFFFFD700\nSpellbound Closed|r")
            else
                spellboundFrame:Show()
                if not gameRunning then
                    UpdateScoreDisplay() -- Force score update
                end
                print("|cFFFFD700\nWelcome to Spellbound!|r")
                DisplayMessage("Welcom To SpellBound", 1.0, 0.843, 0.0, 32)
            end
        else
            -- Invalid command
            print("|cFFFF0000\nInvalid SpellBound command.|r")
			print(helpMessage)
        end
    end
end
