local addonName, SinsToolkit = ...

local frame = CreateFrame("Frame", addonName .. "AutoUnshiftFrame")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
frame:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
local travelFrame = CreateFrame("Frame", addonName .. "DruidAutoFlightFormFrame")
local travelFormLastCancel = 0
local travelFormTimer
local pendingAutoUnshiftValue

local function IsDruid()
    local _, class = UnitClass("player")
    return class == "DRUID"
end

local function IsFeralOrGuardianDruid()
    local _, class = UnitClass("player")
    if class ~= "DRUID" then return false end
    local specIndex = GetSpecialization and GetSpecialization()
    local specID = specIndex and GetSpecializationInfo and GetSpecializationInfo(specIndex)
    return specID == 103 or specID == 104
end

local function IsPlayerInCombat()
    return (InCombatLockdown and InCombatLockdown())
        or (UnitAffectingCombat and UnitAffectingCombat("player"))
end

function SinsToolkit.IsAutoUnshiftFormActive()
    return SinsToolkit.IsFeatureActive
        and SinsToolkit.IsFeatureActive("gseAutoUnshift")
        and IsFeralOrGuardianDruid()
        and IsPlayerInCombat()
end

local function SetAutoUnshift(value)
    if IsPlayerInCombat() then
        pendingAutoUnshiftValue = value and true or false
        frame:RegisterEvent("PLAYER_REGEN_ENABLED")
        return false
    end

    local cvarValue = value and "1" or "0"
    local ok
    if C_CVar and C_CVar.SetCVar then
        ok = pcall(C_CVar.SetCVar, "autoUnshift", cvarValue)
    elseif SetCVar then
        ok = pcall(SetCVar, "autoUnshift", cvarValue)
    end

    if ok then
        pendingAutoUnshiftValue = nil
    else
        pendingAutoUnshiftValue = value and true or false
        frame:RegisterEvent("PLAYER_REGEN_ENABLED")
    end
    return ok == true
end

local function DisableAutoUnshift()
    if IsFeralOrGuardianDruid() then
        SetAutoUnshift(false)
    end
end

local function EnableAutoUnshift()
    SetAutoUnshift(true)
end

local function IsDruidAutoFlightFormActive()
    return SinsToolkit.IsFeatureActive
        and SinsToolkit.IsFeatureActive("druidAutoFlightForm")
        and IsDruid()
end

local function CheckDruidAutoFlightForm()
    if not IsDruidAutoFlightFormActive() then return end
    if InCombatLockdown and InCombatLockdown() then return end
    if UnitAffectingCombat and UnitAffectingCombat("player") then return end
    if IsInInstance and IsInInstance() then return end
    if C_ChallengeMode and C_ChallengeMode.IsChallengeModeActive and C_ChallengeMode.IsChallengeModeActive() then return end
    if not IsFlyableArea or not IsFlyableArea() then return end
    if IsFlying and IsFlying() then return end
    if IsSubmerged and IsSubmerged() then return end
    if not GetShapeshiftFormID or GetShapeshiftFormID() ~= 3 then return end

    local now = GetTime and GetTime() or 0
    if travelFormLastCancel + 5 > now then
        if C_Timer and not travelFormTimer then
            travelFormTimer = C_Timer.NewTimer(travelFormLastCancel + 5 - now, function()
                travelFormTimer = nil
                CheckDruidAutoFlightForm()
            end)
        end
        return
    end

    travelFormLastCancel = now
    if CancelShapeshiftForm then
        CancelShapeshiftForm()
    end
end

function SinsToolkit.ApplyDruidAutoFlightForm()
    if IsDruidAutoFlightFormActive() then
        travelFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
        travelFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
        travelFrame:RegisterEvent("ZONE_CHANGED")
        travelFrame:RegisterEvent("ZONE_CHANGED_INDOORS")
        travelFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
        travelFrame:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
        if C_Timer then
            C_Timer.After(0.2, CheckDruidAutoFlightForm)
        else
            CheckDruidAutoFlightForm()
        end
    else
        travelFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
        travelFrame:UnregisterEvent("PLAYER_REGEN_ENABLED")
        travelFrame:UnregisterEvent("ZONE_CHANGED")
        travelFrame:UnregisterEvent("ZONE_CHANGED_INDOORS")
        travelFrame:UnregisterEvent("ZONE_CHANGED_NEW_AREA")
        travelFrame:UnregisterEvent("UPDATE_SHAPESHIFT_FORM")
        if travelFormTimer then
            travelFormTimer:Cancel()
            travelFormTimer = nil
        end
    end
end

function SinsToolkit.ApplyGSEAutoUnshift()
    local active = SinsToolkit.IsFeatureActive
        and SinsToolkit.IsFeatureActive("gseAutoUnshift")
        and IsFeralOrGuardianDruid()

    if active then
        DisableAutoUnshift()
    else
        EnableAutoUnshift()
        if not IsPlayerInCombat() then
            frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
        end
    end
end

frame:SetScript("OnEvent", function(_, event)
    if event == "PLAYER_LOGIN"
        or event == "PLAYER_ENTERING_WORLD"
        or event == "PLAYER_SPECIALIZATION_CHANGED"
        or event == "UPDATE_SHAPESHIFT_FORM"
        or event == "PLAYER_REGEN_DISABLED" then
        SinsToolkit.ApplyGSEAutoUnshift()
        SinsToolkit.ApplyDruidAutoFlightForm()
    elseif event == "PLAYER_REGEN_ENABLED" then
        if pendingAutoUnshiftValue ~= nil then
            SetAutoUnshift(pendingAutoUnshiftValue)
        end
        SinsToolkit.ApplyGSEAutoUnshift()
    end
end)

travelFrame:SetScript("OnEvent", function()
    CheckDruidAutoFlightForm()
end)

SLASH_SinsToolkitGSEAUTOUNSHIFT1 = "/sau"
SlashCmdList.SinsToolkitGSEAUTOUNSHIFT = function(msg)
    msg = (msg or ""):lower():match("^%s*(.-)%s*$")
    if msg == "toggle" then
        SinsToolkitDB.gseAutoUnshift = not SinsToolkitDB.gseAutoUnshift
        if SinsToolkit.ApplyDependencyGuards then SinsToolkit.ApplyDependencyGuards(false) end
        SinsToolkit.ApplyGSEAutoUnshift()
        if SinsToolkitDB.gseAutoUnshift then
            print("|cff9b59b6[Sin's Toolkit: QOL]|r Auto Unshift for Druids |cff00ff00enabled|r.")
        else
            print("|cff9b59b6[Sin's Toolkit: QOL]|r Auto Unshift for Druids |cffff4040disabled|r.")
        end
    elseif msg == "" or msg == "status" then
        if SinsToolkit.IsFeatureActive and SinsToolkit.IsFeatureActive("gseAutoUnshift") then
            print("|cff9b59b6[Sin's Toolkit: QOL]|r Auto Unshift for Druids is |cff00ff00enabled|r.")
        else
            print("|cff9b59b6[Sin's Toolkit: QOL]|r Auto Unshift for Druids is |cffff4040disabled|r.")
        end
    else
        print("|cff9b59b6[Sin's Toolkit: QOL]|r Use /stk status to check Auto Unshift and automation status.")
        print("|cff9b59b6[Sin's Toolkit: QOL]|r Compatibility command: /sau toggle")
    end
end
