local assets =
{
    Asset("ANIM", "anim/tornado.zip"),
    Asset("ANIM", "anim/tornado_stick.zip"),
    Asset("ANIM", "anim/swap_tornado_stick.zip"),
}

local prefabs =
{
    "tornado",
}

local function getspawnlocation(inst, target)
    local x1, y1, z1 = inst.Transform:GetWorldPosition()
    local x2, y2, z2 = target.Transform:GetWorldPosition()
    return x1 + .15 * (x2 - x1), 0, z1 + .15 * (z2 - z1)
end

local function spawntornado(staff, target, pos)
    local tornado = SpawnPrefab("tornado")
    tornado.WINDSTAFF_CASTER = staff.components.inventoryitem.owner
    tornado.WINDSTAFF_CASTER_ISPLAYER = tornado.WINDSTAFF_CASTER ~= nil and tornado.WINDSTAFF_CASTER:HasTag("player")
    tornado.Transform:SetPosition(getspawnlocation(staff, target))
    tornado.components.knownlocations:RememberLocation("target", target:GetPosition())

    if tornado.WINDSTAFF_CASTER_ISPLAYER then
        tornado.overridepkname = tornado.WINDSTAFF_CASTER:GetDisplayName()
        tornado.overridepkpet = true
    end

    staff.components.finiteuses:Use(1)
end

local function onequip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_tornado_stick", "swap_tornado_stick")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
end

local function onunequip(inst, owner)
    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")
end

local function staff_fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)

    inst.AnimState:SetBank("tornado_stick")
    inst.AnimState:SetBuild("tornado_stick")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("nopunch")

    --Sneak these into pristine state for optimization
    inst:AddTag("quickcast")

    inst.spelltype = "SCIENCE"

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    -------
    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(TUNING.TORNADOSTAFF_USES)
    inst.components.finiteuses:SetUses(TUNING.TORNADOSTAFF_USES)
    inst.components.finiteuses:SetOnFinished(inst.Remove)

    inst:AddComponent("inspectable")

    inst:AddComponent("inventoryitem")

    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip(onequip)
    inst.components.equippable:SetOnUnequip(onunequip)

    inst:AddComponent("spellcaster")
    inst.components.spellcaster.canuseontargets = true
    inst.components.spellcaster.canonlyuseonworkable = true
    inst.components.spellcaster.canonlyuseoncombat = true
    inst.components.spellcaster.quickcast = true
    inst.components.spellcaster:SetSpellFn(spawntornado)
    inst.components.spellcaster.castingstate = "castspell_tornado"

    MakeHauntableLaunch(inst)

    return inst
end

local brain = require("brains/tornadobrain")

local function ontornadolifetime(inst)
    inst.task = nil
    inst.sg:GoToState("despawn")
end

local function SetDuration(inst, duration)
    if inst.task ~= nil then
        inst.task:Cancel()
    end
    inst.task = inst:DoTaskInTime(duration, ontornadolifetime)
end

local function tornado_fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddNetwork()

    inst.AnimState:SetFinalOffset(2)
    inst.AnimState:SetBank("tornado")
    inst.AnimState:SetBuild("tornado")
    inst.AnimState:PlayAnimation("tornado_pre")
    inst.AnimState:PushAnimation("tornado_loop")

    inst.SoundEmitter:PlaySound("dontstarve_DLC001/common/tornado", "spinLoop")

    MakeInventoryPhysics(inst)
    RemovePhysicsColliders(inst)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("knownlocations")

    inst:AddComponent("locomotor")
    inst.components.locomotor.walkspeed = TUNING.TORNADO_WALK_SPEED * .33
    inst.components.locomotor.runspeed = TUNING.TORNADO_WALK_SPEED

    inst:SetStateGraph("SGtornado")
    inst:SetBrain(brain)

    inst.WINDSTAFF_CASTER = nil
    inst.persists = false

    inst.SetDuration = SetDuration
    inst:SetDuration(TUNING.TORNADO_LIFETIME)

    return inst
end

local function LightningStrike(inst)
    local rad = math.random(1,15)
    local angle = math.random() * 2 * PI
    local offset = Vector3(rad * math.cos(angle), 0, -rad * math.sin(angle))
    local pos = inst:GetPosition() + offset
    
	TheWorld:PushEvent("ms_sendlightningstrike", pos)
	TheWorld:PushEvent("ms_forceprecipitation", true)
    --TheWorld.components.seasonmanager:DoLightningStrike(pos)
    --GetSeasonManager():StartPrecip()
    inst.lightning = false
end

local function OnSave(inst, data)
    data.lightning = inst.liightning
end

local function OnLoad(inst, data)
    if data.CanDisarm then 
        inst.CanDisarm = data.CanDisarm
    end
end

local function ontimerdone(inst, data)
    if data.name == "lightning" then
        if math.random() < 0.25 then
        LightningStrike(inst)
        end
    end
end

local function moosetornado_fn()
    local inst = CreateEntity()
    local trans = inst.entity:AddTransform()
    local anim = inst.entity:AddAnimState()
    local sound = inst.entity:AddSoundEmitter()
	inst.entity:AddNetwork()

    anim:SetBank("tornado")
    anim:SetBuild("tornado")
    anim:PlayAnimation("tornado_pre")
    anim:PushAnimation("tornado_loop")
    
    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end
    sound:PlaySound("dontstarve_DLC001/common/tornado", "spinLoop")

    inst:DoTaskInTime(10, function() inst.sg:GoToState("despawn") end)

    MakeInventoryPhysics(inst)
    RemovePhysicsColliders(inst)

    inst:AddComponent("knownlocations")

    inst:AddComponent("locomotor")
    inst.components.locomotor.walkspeed = 5
    inst.components.locomotor.runspeed = 5

    inst:AddComponent("sizetweener")
    inst.components.sizetweener:StartTween(3, 1)

    inst:AddComponent("timer")

    inst:ListenForEvent("timerdone", ontimerdone)

    inst:SetStateGraph("SGtornado_moose")
    inst:SetBrain(require "brains/tornadobrain")

    inst.WINDSTAFF_CASTER = nil

    inst.lightning = false

    return inst
end
return Prefab("staff_tornado", staff_fn, assets, prefabs),
    Prefab("tornado", tornado_fn, assets),
	Prefab("tornado_moose", moosetornado_fn, assets)
