require("stategraphs/commonstates")

local SHAKE_DIST = 40

local function ShakeIfClose(inst)
    local player = GetClosestInstWithTag("player", inst, SHAKE_DIST)
    if player then
        player.components.playercontroller:ShakeCamera(inst, "FULL", 0.35, 0.02, 1.25, SHAKE_DIST)
    end
end

local function StartFlapping(inst)
	local snd = math.random(1,4)
    --inst.SoundEmitter:PlaySound("dontstarve/creatures/together/bee_queen/wings_LP", "flying")
	--inst.SoundEmitter:PlaySound("beequeen/untitled/bee_Queen_wing_V3_" .. snd, "flying")
	inst.SoundEmitter:PlaySound("dontstarve/creatures/bat/flap", "flying")
end

local function FlappingSound(inst)
	local snd = math.random(1,4)
	--inst.SoundEmitter:PlaySound("beequeen/untitled/bee_Queen_wing_V3_" .. snd)
	inst.SoundEmitter:PlaySound("dontstarve/creatures/bat/flap")
end

local function BreathSound(inst)
	local snd = math.random(0,3)
	inst.SoundEmitter:PlaySound("beequeen/untitled/beequeenVO2_00" .. snd)
end

local function SpawnBeeSound(inst)
	local snd = math.random(1,5)
	inst.SoundEmitter:PlaySound("beequeen/untitled/beeQueen_spawn_" .. snd)
end

local function HitSound(inst)
	local snd = math.random(0,8)
	inst.SoundEmitter:PlaySound("beequeen/untitled/beequeen_hit_00" .. snd)
end

local function AttackSound(inst)
	local snd = math.random(0,4)
	inst.SoundEmitter:PlaySound("beequeen/untitled/beequeen_attackpre_00" .. snd)
end

local function RestoreFlapping(inst)
    if not inst.SoundEmitter:PlayingSound("flying") then
        StartFlapping(inst)
    end
end

local function StopFlapping(inst)
    inst.SoundEmitter:KillSound("flying")
end

local function DoScreech(inst)
	local snd = math.random(1,3)
	inst.SoundEmitter:PlaySound("beequeen/untitled/bee_Queen_taunt_lrg_" .. snd)
	ShakeIfClose(inst)
end

local function DoTaunt(inst)
	local snd = math.random(0,6)
	inst.SoundEmitter:PlaySound("beequeen/untitled/beequeen_taunt_00" .. snd)
end

local events=
{
	CommonHandlers.OnLocomote(false,true),
    CommonHandlers.OnSleep(),
    CommonHandlers.OnFreeze(),
    CommonHandlers.OnAttack(),
    CommonHandlers.OnAttacked(),
    CommonHandlers.OnDeath(),	
}

local states=
{
    State
	{
        name = "idle",
        tags = {"idle", "canrotate"},

        onenter = function(inst)
            inst.Physics:Stop()
            inst.AnimState:PlayAnimation("idle_loop")
        end,

		timeline = 
        {
		    TimeEvent(7*FRAMES, FlappingSound),
			TimeEvent(17*FRAMES, FlappingSound),
        },

        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },

    State
	{
        name = "death",
        tags = {"busy"},
        onenter = function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/creatures/spiderqueen/die")
            inst.AnimState:PlayAnimation("death")
			inst.SoundEmitter:KillSound("flying")
            inst.Physics:Stop()
            RemovePhysicsColliders(inst)            
            inst.components.lootdropper:DropLoot(Vector3(inst.Transform:GetWorldPosition()))            
        end,
		
		timeline =
        {
            TimeEvent(14*FRAMES, DoScreech),
            TimeEvent(28*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/bee/beehive_hit") end),
        },	
    },
	
	State
	{
        name = "walk_start",
        tags = {"moving", "canrotate"},

        onenter = function(inst)
            inst.components.locomotor:WalkForward()
            inst.AnimState:PlayAnimation("walk_pre")
        end,
		
		timeline = 
        {
		    TimeEvent(7*FRAMES, FlappingSound),
			TimeEvent(17*FRAMES, FlappingSound),
        },
		
		events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("walk") end),
        },		
    },
	
	State
	{
        name = "walk",
        tags = {"moving", "canrotate"},

        onenter = function(inst)
            inst.components.locomotor:WalkForward()
            inst.AnimState:PlayAnimation("walk_loop")
        end,
		
		timeline = 
        {
			TimeEvent(1*FRAMES, BreathSound),
		    TimeEvent(7*FRAMES, FlappingSound),
			TimeEvent(17*FRAMES, FlappingSound),
        },
		
		events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("walk") end),
        },
    }, 

	State
	{
        name = "walk_stop",
        tags = {"canrotate"},

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("walk_pst")
        end,
		
		timeline = 
        {
			TimeEvent(7*FRAMES, FlappingSound),
			TimeEvent(17*FRAMES, FlappingSound),
        },
		
		events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },	
   
    State
	{
        name = "attack",
        tags = {"attack", "busy"},
        
        onenter = function(inst)
            inst.components.combat:StartAttack()
			inst.AnimState:PlayAnimation("atk")
            inst.Physics:Stop()
        end,
        
        timeline=
        {
			TimeEvent(1*FRAMES, AttackSound),
			TimeEvent(14 * FRAMES, function(inst)
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
                inst.components.combat:DoAttack()
            end),
        },
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },

	State
	{
        name = "spawnbees",
        tags = {"spawnbees", "busy", "nosleep", "nofreeze"},

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("spawn")
			SpawnBeeSound(inst)
        end,

        timeline =
        {
            TimeEvent(16*FRAMES, function(inst)
				local player = GetPlayer()
				local birth = math.random(3,5)
				for k = 1, birth do
					local angle = inst.Transform:GetRotation()/DEGREES
					local prefab = "beeguard"--(inst.components.combat.target and math.random() < .999) and "killerbee" or "bee"
					--if inst.components.leader.numfollowers < inst.maxguard then
						--prefab = "beeguard"
					--end
					local bee = inst.components.lootdropper:SpawnLootPrefab(prefab)
					local rad = bee.Physics:GetRadius()+inst.Physics:GetRadius()+.25
					local pt = Vector3(inst.Transform:GetWorldPosition())
					if bee then
						bee.Transform:SetPosition(pt.x + rad*math.cos(angle), pt.y, pt.z + rad*math.sin(angle))
						if bee.components.follower then
							inst.components.leader:AddFollower(bee)
							bee.sg:GoToState("spawnin")
						end
						if inst.components.combat.target then
							bee.components.combat:SetTarget(inst.components.combat.target)
						end
					end
				end
            end),
        },

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
	
	State
	{
        name = "focustarget",
        tags = {"focustarget", "busy", "nosleep", "nofreeze"},

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
			local command = math.random(1,3)
            inst.AnimState:PlayAnimation("command" .. command)	
			inst.components.health:SetAbsorptionAmount(0.75)
        end,

        timeline =
        {
            TimeEvent(8*FRAMES, DoTaunt),
			TimeEvent(11*FRAMES, AttackSound),
        },

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
		
		onexit = function(inst)
			inst.components.health:SetAbsorptionAmount(0.0)
        end,	
    },
	
	State
	{
        name = "emerge",
        tags = {"busy", "nosleep", "nofreeze", "noattack"},

        onenter = function(inst)
			StopFlapping(inst)
            inst.Transform:SetNoFaced()
            inst.components.locomotor:StopMoving()
            inst.components.health:SetInvincible(true)
            inst.AnimState:PlayAnimation("enter")
			inst.SoundEmitter:PlaySound("beequeen/untitled/beeQueen_enter_v2")		
        end,
		
		timeline =
        {
            TimeEvent(31*FRAMES, DoTaunt),
            TimeEvent(35*FRAMES, StartFlapping),
        },

        events =
        {
			EventHandler("animover", function(inst) inst.sg:GoToState("screech") end),
        },

        onexit = function(inst)
			RestoreFlapping(inst)
            inst.Transform:SetSixFaced()
            inst.components.health:SetInvincible(false)
        end,
    },
	
	State
	{
        name = "screech",
        tags = {"screech", "busy", "nosleep", "nofreeze"},

        onenter = function(inst)          
			inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("screech")
			if (IsDLCEnabled(CAPY_DLC) or IsDLCEnabled(REIGN_OF_GIANTS)) then  
				inst.components.health:SetAbsorptionAmount(0.75) 
			else
				inst.components.health:SetAbsorbAmount(0.75)	
			end
        end,
		
		timeline = 
        {
		    TimeEvent(8*FRAMES, DoScreech),
            TimeEvent(33*FRAMES, DoScreech),
        },

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("spawnbees") end),
        },
		
		onexit = function(inst)
			if (IsDLCEnabled(CAPY_DLC) or IsDLCEnabled(REIGN_OF_GIANTS)) then  
				inst.components.health:SetAbsorptionAmount(0.0) 
			else
				inst.components.health:SetAbsorbAmount(0.0)	
			end
        end,
    },
	
	State
	{
        name = "taunt",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.Physics:Stop()
            inst.AnimState:PlayAnimation("screech")
			if (IsDLCEnabled(CAPY_DLC) or IsDLCEnabled(REIGN_OF_GIANTS)) then  
				inst.components.health:SetAbsorptionAmount(0.75) 
			else
				inst.components.health:SetAbsorbAmount(0.75)	
			end
        end,
		
		timeline = 
        {
		    TimeEvent(8*FRAMES, DoScreech),
            TimeEvent(33*FRAMES, DoScreech),
        },
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
		
		onexit = function(inst)
						if (IsDLCEnabled(CAPY_DLC) or IsDLCEnabled(REIGN_OF_GIANTS)) then  
				inst.components.health:SetAbsorptionAmount(0.0) 
			else
				inst.components.health:SetAbsorbAmount(0.0)	
			end
        end,
    },

    State
	{
        name = "hit",
        tags = {"hit"},

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("hit")
			HitSound(inst)
        end,

		events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },	
    },
	
	State
	{
		name = "frozen",
		tags = {"busy"},
		
        onenter = function(inst)
            inst.AnimState:PlayAnimation("frozen")
            inst.Physics:Stop()
            StopFlapping(inst)
        end,
		
		onexit = function(inst)
            StartFlapping(inst)
        end,
    },
}

CommonStates.AddSimpleState(states,"refuse", "hungry", {"busy"})

local function OnOverrideFrozenSymbols(inst)
    StopFlapping(inst)
end

local function OnClearFrozenSymbols(inst)
    StartFlapping(inst)
end

CommonStates.AddFrozenStates(states)

CommonStates.AddSleepStates(states,
{
	starttimeline = 
	{
		TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/spiderqueen/fallasleep") end ),
		TimeEvent(0*FRAMES, StopFlapping),
	},
	sleeptimeline = 
	{
		TimeEvent(35*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/bee_queen/sleep") end ),
	},
	waketimeline = 
	{
		TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/spiderqueen/wakeup") end ),
		TimeEvent(0*FRAMES, StartFlapping),
	},
})

return StateGraph("beequeen", states, events, "idle")