local addonName, SinsToolkit = ...

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

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 DisableAutoUnshift()
    if IsFeralOrGuardianDruid() then
        if C_CVar and C_CVar.SetCVar then
            C_CVar.SetCVar("autoUnshift", 0)
        else
            SetCVar("autoUnshift", 0)
        end
    end
end

local function EnableAutoUnshift()
    if IsFeralOrGuardianDruid() then
        if C_CVar and C_CVar.SetCVar then
            C_CVar.SetCVar("autoUnshift", 1)
        else
            SetCVar("autoUnshift", 1)
        end
    end
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()
    if SinsToolkit.IsGSEAvailable and not SinsToolkit.IsGSEAvailable() then
        frame:UnregisterEvent("PLAYER_REGEN_DISABLED")
        frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
        EnableAutoUnshift()
        return
    end

    if SinsToolkit.IsFeatureActive and SinsToolkit.IsFeatureActive("gseAutoUnshift") and IsFeralOrGuardianDruid() then
        frame:RegisterEvent("PLAYER_REGEN_DISABLED")
        frame:RegisterEvent("PLAYER_REGEN_ENABLED")
        if InCombatLockdown and InCombatLockdown() then
            DisableAutoUnshift()
        else
            EnableAutoUnshift()
        end
    else
        frame:UnregisterEvent("PLAYER_REGEN_DISABLED")
        frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
        EnableAutoUnshift()
    end
end

frame:SetScript("OnEvent", function(_, event)
    if event == "PLAYER_LOGIN" then
        SinsToolkit.ApplyGSEAutoUnshift()
        SinsToolkit.ApplyDruidAutoFlightForm()
    elseif event == "PLAYER_REGEN_DISABLED" then
        DisableAutoUnshift()
    elseif event == "PLAYER_REGEN_ENABLED" then
        EnableAutoUnshift()
    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]|r Auto Unshift for Druids |cff00ff00enabled|r.")
        else
            print("|cff9b59b6[Sin's Toolkit]|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]|r Auto Unshift for Druids is |cff00ff00enabled|r.")
        else
            print("|cff9b59b6[Sin's Toolkit]|r Auto Unshift for Druids is |cffff4040disabled|r.")
        end
    else
        print("|cff9b59b6[Sin's Toolkit]|r Usage: /sau status")
        print("|cff9b59b6[Sin's Toolkit]|r Usage: /sau toggle")
    end
end
