-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | 		LauInterrupt v1.7 		  |
-- ====================================
local addonName, addon = ...
addon.version = "1.7"
LauInterruptDB = LauInterruptDB or {}
addon.db = LauInterruptDB
local interruptSpells = {
    ["WARRIOR"] = {6552, 6552, 6552},
    ["HUNTER"] = {147362, 147362, 187707},
    ["DRUID"] = {78675, 106839, 106839, nil},
    ["SHAMAN"] = {57994, 57994, 57994},
    ["ROGUE"] = {1766, 1766, 1766},
    ["MAGE"] = {2139, 2139, 2139},
    ["PRIEST"] = {nil, nil, 15487},
    ["WARLOCK"] = {19647, 19647, 19647},
    ["MONK"] = {116705, nil, 116705},
    ["PALADIN"] = {nil, 96231, 96231},
    ["DEATHKNIGHT"] = {47528, 47528, 47528},
    ["DEMONHUNTER"] = {183752, 183752, 183752},
    ["EVOKER"] = {351338, nil, 351338},
}
local fallbackCooldowns = {
    ["WARRIOR"] = {
        [1] = 15, -- Arms
        [2] = 15, -- Fury
        [3] = 15, -- Protection
    },
    ["HUNTER"] = {
        [1] = 24, -- Marksmanship
        [2] = 24, -- Beast Mastery
        [3] = 15, -- Survival
    },
    ["DRUID"] = {
        [1] = 60, -- Balance (Solar Beam)
        [2] = 15, -- Feral (Skull Bash)
        [3] = 15, -- Guardian (Skull Bash)
    },
    ["SHAMAN"] = {
        [1] = 12, -- Elemental
        [2] = 12, -- Enhancement
        [3] = 30, -- Restoration (Wind Shear 30s)
    },
    ["ROGUE"] = {
        [1] = 15, -- Assassination
        [2] = 15, -- Outlaw
        [3] = 15, -- Subtlety
    },
    ["MAGE"] = {
        [1] = 24, -- Arcane
        [2] = 24, -- Fire
        [3] = 24, -- Frost
    },
    ["PRIEST"] = {
        [3] = 45, -- Shadow
    },
    ["WARLOCK"] = {
        [1] = 24, -- Affliction
        [2] = 24, -- Demonology
        [3] = 24, -- Destruction
    },
    ["MONK"] = {
        [1] = 15, -- Brewmaster
        [3] = 15, -- Windwalker
    },
    ["PALADIN"] = {
        [2] = 15, -- Protection
        [3] = 15, -- Retribution
    },
    ["DEATHKNIGHT"] = {
        [1] = 15, -- Blood
        [2] = 15, -- Frost
        [3] = 15, -- Unholy
    },
    ["DEMONHUNTER"] = {
        [1] = 15, -- Havoc
        [2] = 15, -- Vengeance
        [3] = 15, -- Vengeance
    },
    ["EVOKER"] = {
        [1] = 20, -- Devastation
        [3] = 20, -- Augmentation
    },
}
local frame = CreateFrame("Frame", "LauInterruptFrame", UIParent, "BackdropTemplate")
frame:SetSize(200, 30)
frame:SetPoint("CENTER")
frame:SetBackdrop({
    bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Buttons\\WHITE8X8",
    tile = false,
    edgeSize = 1,
    insets = { left = 1, right = 1, top = 1, bottom = 1 }
})
frame:SetBackdropColor(0.08, 0.08, 0.08, 0.65)
frame:SetBackdropBorderColor(0, 0, 0, 1)
frame:Hide()
local icon = frame:CreateTexture(nil, "ARTWORK")
icon:SetSize(26, 26)
icon:SetPoint("LEFT", frame, "LEFT", 1, 0)
icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
local bar = CreateFrame("StatusBar", nil, frame)
bar:SetPoint("LEFT", icon, "RIGHT", 1, 0)
bar:SetPoint("RIGHT", frame, "RIGHT", -1, 0)
bar:SetPoint("TOP", frame, "TOP", 0, -1)
bar:SetPoint("BOTTOM", frame, "BOTTOM", 0, 1)
bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
bar:SetMinMaxValues(0, 1)
bar:SetValue(0)
local cooldownText = bar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
cooldownText:SetPoint("RIGHT", bar, "RIGHT", -5, 0)
cooldownText:SetJustifyH("RIGHT")
cooldownText:SetTextColor(1, 1, 1, 1)
local font, _, flags = cooldownText:GetFont()
local interruptSpellID = nil
local isLocked = true
local lastUpdate = 0
local updateInterval = 0.03
local cooldownEndTime = 0
local cooldownDuration = 0
local LSM = LibStub and LibStub("LibSharedMedia-3.0", true)
local UpdateOptionsPanel
local widthSlider, widthEditBox, heightSlider, heightEditBox, fontSizeSlider, fontSizeEditBox
local function ShouldShowFrame()
    if addon.db.hideSolo then
        if not IsInGroup() then
            return false
        end
    end
   
    if addon.db.showOnlyInstance then
        local inInstance, instanceType = IsInInstance()
        if not inInstance or (instanceType ~= "party" and instanceType ~= "raid") then
            return false
        end
    end
   
    return true
end
local function UpdateFrameVisibility()
    if interruptSpellID and ShouldShowFrame() then
        frame:Show()
    else
        frame:Hide()
    end
end
local function UpdateSpell()
    local _, class = UnitClass("player")
    local spec = GetSpecialization()
    interruptSpellID = interruptSpells[class] and interruptSpells[class][spec] or nil
 
    if interruptSpellID then
        icon:SetTexture(C_Spell.GetSpellTexture(interruptSpellID))
        local color = RAID_CLASS_COLORS[class]
        bar:SetStatusBarColor(color.r, color.g, color.b, 1)
    end
   
    UpdateFrameVisibility()
end
local function SavePosition()
    local point, _, relativePoint, xOfs, yOfs = frame:GetPoint()
    addon.db.position = {point, "UIParent", relativePoint, xOfs, yOfs}
end
local function ToggleLock()
    isLocked = not isLocked
    addon.db.isLocked = isLocked
 
    if isLocked then
        frame:SetMovable(false)
        frame:EnableMouse(false)
        frame:SetScript("OnMouseDown", nil)
        frame:SetScript("OnMouseUp", nil)
        SavePosition()
    else
        frame:SetMovable(true)
        frame:EnableMouse(true)
        frame:SetScript("OnMouseDown", function(self, button)
            if button == "LeftButton" then self:StartMoving() end
        end)
        frame:SetScript("OnMouseUp", function(self, button)
            if button == "LeftButton" then
                self:StopMovingOrSizing()
                SavePosition()
            end
        end)
    end
end
local function CreateSliderWithEditBox(parent, name, anchorPoint, anchorTo, xOff, yOff, minVal, maxVal, currentVal, label)
    local slider = CreateFrame("Slider", name, parent, "OptionsSliderTemplate")
    slider:SetPoint(anchorPoint, anchorTo, "BOTTOMLEFT", xOff, yOff)
    slider:SetSize(200, 20)
    slider:SetMinMaxValues(minVal, maxVal)
    slider:SetValueStep(1)
    slider:SetObeyStepOnDrag(true)
    _G[slider:GetName() .. "Low"]:SetText(tostring(minVal))
    _G[slider:GetName() .. "High"]:SetText(tostring(maxVal))
    _G[slider:GetName() .. "Text"]:SetText(label .. ": " .. currentVal)
    slider:SetValue(currentVal)
   
    local editBox = CreateFrame("EditBox", name .. "EditBox", parent, "InputBoxTemplate")
    editBox:SetPoint("LEFT", slider, "RIGHT", 10, 0)
    editBox:SetSize(50, 20)
    editBox:SetAutoFocus(false)
    editBox:SetNumeric(true)
    editBox:SetMaxLetters(3)
    editBox:SetText(tostring(currentVal))
   
    editBox:SetScript("OnEnterPressed", function(self)
        local value = tonumber(self:GetText()) or currentVal
        value = math.max(minVal, math.min(maxVal, value))
        slider:SetValue(value)
        self:ClearFocus()
    end)
   
    editBox:SetScript("OnEscapePressed", function(self)
        self:SetText(tostring(math.floor(slider:GetValue())))
        self:ClearFocus()
    end)
   
    slider:SetScript("OnValueChanged", function(self, value)
        value = math.floor(value)
        editBox:SetText(tostring(value))
        _G[self:GetName() .. "Text"]:SetText(label .. ": " .. value)
    end)
   
    return slider, editBox
end
local function CreateDropdown(parent, name, anchorPoint, anchorTo, xOff, yOff, label, options, currentValue, onChange)
    local dropdownLabel = parent:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    dropdownLabel:SetPoint(anchorPoint, anchorTo, "BOTTOMLEFT", xOff, yOff)
    dropdownLabel:SetText(label)
   
    local dropdown = CreateFrame("Frame", name, parent, "UIDropDownMenuTemplate")
    dropdown:SetPoint("TOPLEFT", dropdownLabel, "BOTTOMLEFT", -15, -5)
   
    UIDropDownMenu_SetWidth(dropdown, 150)
    UIDropDownMenu_SetText(dropdown, currentValue)
   
    UIDropDownMenu_Initialize(dropdown, function(self, level)
        local info = UIDropDownMenu_CreateInfo()
        for _, option in ipairs(options) do
            info.text = option
            info.func = function()
                UIDropDownMenu_SetText(dropdown, option)
                onChange(option)
            end
            info.checked = (option == UIDropDownMenu_GetText(dropdown))
            UIDropDownMenu_AddButton(info)
        end
    end)
   
    return dropdown, dropdownLabel
end
frame:SetScript("OnUpdate", function(self, elapsed)
    lastUpdate = lastUpdate + elapsed
    if lastUpdate < updateInterval or not interruptSpellID then return end
    local now = GetTime()
    local progress = 0
    if cooldownEndTime > now then
        local elapsed = now - (cooldownEndTime - cooldownDuration)
        progress = math.min(1, math.max(0, elapsed / cooldownDuration))
        local remaining = math.ceil(cooldownEndTime - now)
        cooldownText:SetFont(font, addon.db.fontSize, "OUTLINE")
        cooldownText:SetText(remaining)
    else
        progress = 1
        cooldownDuration = 0
        cooldownText:SetFont(font, addon.db.fontSize - 2, "OUTLINE")
        cooldownText:SetText("Ready")
    end
    bar:SetValue(progress)
    bar:SetAlpha(progress > 0 and 0.85 or 1.0)
    lastUpdate = 0
end)
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
eventFrame:RegisterEvent("SPELL_UPDATE_COOLDOWN")
eventFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
eventFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:SetScript("OnEvent", function(self, event, unit, castGUID, spellID)
    if event == "PLAYER_LOGIN" then
        addon.db = LauInterruptDB or {}
        LauInterruptDB = addon.db
        addon.db.position = addon.db.position or {"CENTER", "UIParent", "CENTER", 0, 0}
        addon.db.isLocked = addon.db.isLocked ~= false
        addon.db.barSize = addon.db.barSize or {width = 200, height = 30}
        addon.db.texture = addon.db.texture or "Interface\\TargetingFrame\\UI-StatusBar"
        addon.db.fontSize = addon.db.fontSize or 16
        addon.db.hideText = addon.db.hideText or false
        addon.db.hideSolo = addon.db.hideSolo or false
        addon.db.showOnlyInstance = addon.db.showOnlyInstance or false
        if addon.db.position then frame:SetPoint(unpack(addon.db.position)) end
        if addon.db.barSize then
            local bs = addon.db.barSize
            frame:SetSize(bs.width or 200, bs.height or 30)
            icon:SetSize((bs.height or 30) - 4, (bs.height or 30) - 4)
        end
        if addon.db.texture then bar:SetStatusBarTexture(addon.db.texture) end
        cooldownText:SetFont(font, addon.db.fontSize, "OUTLINE")
        if addon.db.hideText then cooldownText:Hide() else cooldownText:Show() end
        isLocked = addon.db.isLocked
        UpdateSpell()
        UpdateOptionsPanel()
    elseif event == "ACTIVE_TALENT_GROUP_CHANGED" or event == "SPELL_UPDATE_COOLDOWN" then
        UpdateSpell()
    elseif event == "GROUP_ROSTER_UPDATE" or event == "ZONE_CHANGED_NEW_AREA" or event == "PLAYER_ENTERING_WORLD" then
        UpdateFrameVisibility()
    elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
        local _, class = UnitClass("player")
        local spec = GetSpecialization()
 
        if unit == "player" and spellID == interruptSpellID then
            local duration = fallbackCooldowns[class] and fallbackCooldowns[class][spec] or 15
            cooldownDuration = duration
            cooldownEndTime = GetTime() + duration
     
        elseif class == "WARLOCK" and unit == "pet" and spellID == 19647 then
            local duration = 24
            cooldownDuration = duration
            cooldownEndTime = GetTime() + duration
        end
    end
end)
local optionsPanel = CreateFrame("Frame")
optionsPanel.name = "LauInterrupt"
local category = Settings.RegisterCanvasLayoutCategory(optionsPanel, optionsPanel.name, optionsPanel.name)
category.ID = optionsPanel.name
Settings.RegisterAddOnCategory(category)
optionsPanel:SetScript("OnShow", function()

    if widthEditBox then
        widthEditBox:SetText(tostring(addon.db.barSize.width or 200))
    end
    if heightEditBox then
        heightEditBox:SetText(tostring(addon.db.barSize.height or 30))
    end
    if fontSizeEditBox then
        fontSizeEditBox:SetText(tostring(addon.db.fontSize or 16))
    end
    UpdateOptionsPanel()
end)
local title = optionsPanel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
title:SetPoint("TOPLEFT", 16, -16)
title:SetText("LauInterrupt")
local lockButton = CreateFrame("Button", nil, optionsPanel, "UIPanelButtonTemplate")
lockButton:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -20)
lockButton:SetSize(100, 25)
lockButton:SetText(isLocked and "Unlock" or "Lock")
lockButton:SetScript("OnClick", function()
    ToggleLock()
    lockButton:SetText(isLocked and "Unlock" or "Lock")
end)
widthSlider, widthEditBox = CreateSliderWithEditBox(
    optionsPanel,
    "LauInterruptWidthSlider",
    "TOPLEFT",
    lockButton,
    0,
    -40,
    100,
    400,
    200,  -- Default inicial
    "Width"
)
widthSlider:SetScript("OnValueChanged", function(self, value)
    value = math.floor(value)
    addon.db.barSize = addon.db.barSize or {}
    addon.db.barSize.width = value
    frame:SetWidth(value)
end)
heightSlider, heightEditBox = CreateSliderWithEditBox(
    optionsPanel,
    "LauInterruptHeightSlider",
    "TOPLEFT",
    widthSlider,
    0,
    -30,
    20,
    60,
    30,  -- Default inicial
    "Height"
)
heightSlider:SetScript("OnValueChanged", function(self, value)
    value = math.floor(value)
    addon.db.barSize = addon.db.barSize or {}
    addon.db.barSize.height = value
    frame:SetHeight(value)
    icon:SetSize(value - 4, value - 4)
end)
local lastAnchor = heightSlider
local xOffset = 0
if LSM then
    local textureButton = CreateFrame("Button", nil, optionsPanel, "UIPanelButtonTemplate")
    textureButton:SetPoint("TOPLEFT", heightSlider, "BOTTOMLEFT", 0, -30)
    textureButton:SetSize(200, 25)
    textureButton:SetText("Select Texture")
    local texturePicker = CreateFrame("Frame", "LauInterruptTexturePicker", optionsPanel, "BackdropTemplate")
    texturePicker:SetSize(300, 400)
    texturePicker:SetPoint("LEFT", textureButton, "RIGHT", 10, 0)
    texturePicker: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 }
    })
    texturePicker:SetBackdropColor(0, 0, 0, 0.9)
    texturePicker:Hide()
    local pickerTitle = texturePicker:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    pickerTitle:SetPoint("TOP", 0, -15)
    pickerTitle:SetText("Select Status Bar Texture")
    local scrollFrame = CreateFrame("ScrollFrame", nil, texturePicker, "UIPanelScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT", 16, -40)
    scrollFrame:SetPoint("BOTTOMRIGHT", -32, 45)
    local scrollChild = CreateFrame("Frame", nil, scrollFrame)
    scrollChild:SetSize(250, 1)
    scrollFrame:SetScrollChild(scrollChild)
   
    local closeButton = CreateFrame("Button", nil, texturePicker, "UIPanelButtonTemplate")
    closeButton:SetPoint("BOTTOM", 0, 10)
    closeButton:SetSize(100, 25)
    closeButton:SetText("Close")
    closeButton:SetScript("OnClick", function() texturePicker:Hide() end)
   
    local function PopulateTextures()
        for _, child in pairs({scrollChild:GetChildren()}) do
            child:Hide()
            child:SetParent(nil)
        end
       
        local textures = LSM:List("statusbar") or {"Interface\\TargetingFrame\\UI-StatusBar"}
        table.sort(textures)
       
        local yOffset = 0
        for i, texName in ipairs(textures) do
            local texPath = LSM:Fetch("statusbar", texName)
            local texButton = CreateFrame("Button", nil, scrollChild, "BackdropTemplate")
            texButton:SetSize(240, 30)
            texButton:SetPoint("TOPLEFT", 5, -yOffset)
            texButton:SetBackdrop({
                bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
                edgeFile = "Interface\\Buttons\\WHITE8X8",
                tile = false, edgeSize = 1,
                insets = { left = 1, right = 1, top = 1, bottom = 1 }
            })
            texButton:SetBackdropColor(0.1, 0.1, 0.1, 0.8)
            texButton:SetBackdropBorderColor(0.3, 0.3, 0.3, 1)
           
            local preview = texButton:CreateTexture(nil, "ARTWORK")
            preview:SetSize(200, 20)
            preview:SetPoint("LEFT", 5, 0)
            preview:SetTexture(texPath)
            preview:SetVertexColor(1, 1, 1, 1)
           
            local texLabel = texButton:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            texLabel:SetPoint("RIGHT", -5, 0)
            texLabel:SetText(texName)
            texLabel:SetTextColor(0.8, 0.8, 0.8, 1)
           
            texButton:SetScript("OnEnter", function(self)
                self:SetBackdropBorderColor(1, 1, 1, 1)
                texLabel:SetTextColor(1, 1, 1, 1)
            end)
            texButton:SetScript("OnLeave", function(self)
                self:SetBackdropBorderColor(0.3, 0.3, 0.3, 1)
                texLabel:SetTextColor(0.8, 0.8, 0.8, 1)
            end)
           
            texButton:SetScript("OnClick", function()
                bar:SetStatusBarTexture(texPath)
                addon.db.texture = texPath
                addon.db.textureName = texName
                textureButton:SetText(texName:sub(1, 20) .. (texName:len() > 20 and "..." or ""))
                texturePicker:Hide()
            end)
           
            yOffset = yOffset + 32
        end
       
        scrollChild:SetHeight(math.max(400, yOffset))
    end
   
    textureButton:SetScript("OnClick", function()
        if texturePicker:IsShown() then
            texturePicker:Hide()
        else
            PopulateTextures()
            texturePicker:Show()
        end
    end)
   
    if addon.db.textureName then
        local displayName = addon.db.textureName:sub(1, 20) .. (addon.db.textureName:len() > 20 and "..." or "")
        textureButton:SetText(displayName)
    end
   
    lastAnchor = textureButton
    xOffset = 0
end
fontSizeSlider, fontSizeEditBox = CreateSliderWithEditBox(
    optionsPanel,
    "LauInterruptFontSizeSlider",
    "TOPLEFT",
    lastAnchor,
    xOffset,
    -30,
    8,
    32,
    16,  -- Default inicial
    "Font Size"
)
fontSizeSlider:SetScript("OnValueChanged", function(self, value)
    value = math.floor(value)
    addon.db.fontSize = value
    cooldownText:SetFont(font, value, "OUTLINE")
end)
local hideTextCheck = CreateFrame("CheckButton", "LauInterruptHideTextCheck", optionsPanel, "UICheckButtonTemplate")
hideTextCheck:SetPoint("TOPLEFT", fontSizeSlider, "BOTTOMLEFT", 0, -20)
_G[hideTextCheck:GetName() .. "Text"]:SetText("Hide Cooldown Text")
hideTextCheck:SetChecked(addon.db.hideText)
hideTextCheck:SetScript("OnClick", function(self)
    addon.db.hideText = self:GetChecked()
    if addon.db.hideText then
        cooldownText:Hide()
    else
        cooldownText:Show()
    end
end)
local hideSoloCheck = CreateFrame("CheckButton", "LauInterruptHideSoloCheck", optionsPanel, "UICheckButtonTemplate")
hideSoloCheck:SetPoint("TOPLEFT", hideTextCheck, "BOTTOMLEFT", 0, -10)
_G[hideSoloCheck:GetName() .. "Text"]:SetText("Hide while solo")
hideSoloCheck:SetChecked(addon.db.hideSolo)
hideSoloCheck:SetScript("OnClick", function(self)
    addon.db.hideSolo = self:GetChecked()
    UpdateFrameVisibility()
end)
local showOnlyInstanceCheck = CreateFrame("CheckButton", "LauInterruptShowOnlyInstanceCheck", optionsPanel, "UICheckButtonTemplate")
showOnlyInstanceCheck:SetPoint("TOPLEFT", hideSoloCheck, "BOTTOMLEFT", 0, -10)
_G[showOnlyInstanceCheck:GetName() .. "Text"]:SetText("Show only in instance")
showOnlyInstanceCheck:SetChecked(addon.db.showOnlyInstance)
showOnlyInstanceCheck:SetScript("OnClick", function(self)
    addon.db.showOnlyInstance = self:GetChecked()
    UpdateFrameVisibility()
end)
UpdateOptionsPanel = function()
    if widthSlider then
        widthSlider:SetValue(addon.db.barSize.width or 200)
        _G[widthSlider:GetName() .. "Text"]:SetText("Width: " .. (addon.db.barSize.width or 200))
    end
   
    if heightSlider then
        heightSlider:SetValue(addon.db.barSize.height or 30)
        _G[heightSlider:GetName() .. "Text"]:SetText("Height: " .. (addon.db.barSize.height or 30))
    end
   
    if fontSizeSlider then
        fontSizeSlider:SetValue(addon.db.fontSize or 16)
        _G[fontSizeSlider:GetName() .. "Text"]:SetText("Font Size: " .. (addon.db.fontSize or 16))
    end
   
    if hideTextCheck then
        hideTextCheck:SetChecked(addon.db.hideText or false)
    end
   
    if hideSoloCheck then
        hideSoloCheck:SetChecked(addon.db.hideSolo or false)
    end
   
    if showOnlyInstanceCheck then
        showOnlyInstanceCheck:SetChecked(addon.db.showOnlyInstance or false)
    end
 
    if lockButton then
        lockButton:SetText(isLocked and "Unlock" or "Lock")
    end
   
    if LSM and textureButton and addon.db.textureName then
        local displayName = addon.db.textureName:sub(1, 20) .. (addon.db.textureName:len() > 20 and "..." or "")
        textureButton:SetText(displayName)
    end
end