require("stategraphs/commonstates")

local actionhandlers = 
{
    
    ActionHandler(ACTIONS.CHOP, "work"),
    ActionHandler(ACTIONS.MINE, "work"),
    ActionHandler(ACTIONS.DIG, "work"),
    ActionHandler(ACTIONS.HAMMER, "work"),
    ActionHandler(ACTIONS.EAT, "eat"),
    ActionHandler(ACTIONS.ATTACK, "attack"),
    ActionHandler(ACTIONS.FORCEATTACK, "attack")
}


local events=
{
    CommonHandlers.OnLocomote(true,false),
    CommonHandlers.OnAttack(),
    CommonHandlers.OnAttacked(),
    CommonHandlers.OnDeath(),
    EventHandler("transform_person", function(inst) inst.sg:GoToState("towoodie") end)
}

local states=
{
    
    State{
        name = "towoodie",
        tags = {"busy"},
        onenter = function(inst)
            inst.Physics:Stop()            
            inst.AnimState:PlayAnimation("death")
            inst.sg:SetTimeout(3)
            inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/death_beaver")
            inst.components.beaverness.doing_transform = true
        end,

        timeline =
        {
            TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:KillSound("beavermusic") end)
        },
        
        ontimeout = function(inst)
            inst:ScreenFade(false, 2)
			-- Adding this as an alternative to cutting to the next day
			if not TheWorld.state.isnight then
				SpawnPrefab("spawnlight").Transform:SetPosition(inst:GetPosition():Get())
			end
            inst:DoTaskInTime(2, function() 
                
                -- TheWorld:PushEvent("ms_nextcycle") -- can't do this because of shared time
                
                inst.components.beaverness.makeperson(inst)
                inst.components.sanity:SetPercent(.25)
                inst.components.health:SetPercent(.33)
                inst.components.hunger:SetPercent(.25)
                inst.components.beaverness.doing_transform = false
                inst.sg:GoToState("wakeup")
                inst:ScreenFade(true, 1)
            end)
        end
    },

    State{
        name = "transform_pst",
        tags = {"busy"},
        onenter = function(inst)
			inst.components.playercontroller:Enable(false)
            inst.Physics:Stop()            
            inst.AnimState:PlayAnimation("transform_pst")
            inst.components.health:SetInvincible(true)
        end,
        
        onexit = function(inst)
            inst.components.health:SetInvincible(false)
            inst.components.playercontroller:Enable(true)
        end,
        
        events=
        {
            EventHandler("animover", function(inst) TheCamera:SetDistance(30) inst.sg:GoToState("idle") end ),
        },        
    },    

    State{
        name = "work",
        tags = {"busy", "working"},
        
        onenter = function(inst)
            inst.Physics:Stop()            
            inst.AnimState:PlayAnimation("atk")
            inst.sg.statemem.action = inst:GetBufferedAction()
        end,
        
        timeline=
        {
            TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh") end),
            TimeEvent(6*FRAMES, function(inst) inst:PerformBufferedAction() end),
            TimeEvent(7*FRAMES, function(inst) inst.sg:RemoveStateTag("working") inst.sg:RemoveStateTag("busy") inst.sg:AddStateTag("idle") end),
            TimeEvent(8*FRAMES, function(inst)
                if inst.components.playercontroller ~= nil and
                    inst.components.playercontroller:IsAnyOfControlsPressed(
                        CONTROL_PRIMARY,
                        CONTROL_ACTION) and 
                    inst.sg.statemem.action and 
                    inst.sg.statemem.action:IsValid() and 
                    inst.sg.statemem.action.target and 
                    inst.sg.statemem.action.target:IsActionValid(inst.sg.statemem.action.action) and 
                    inst.sg.statemem.action.target.components.workable then
                        inst:ClearBufferedAction()
                        inst:PushBufferedAction(inst.sg.statemem.action)
                end
            end),            
        },
    },

    State{
        name = "eat",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.Physics:Stop()            
            inst.AnimState:PlayAnimation("eat")
            inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/eat_beaver") 
        end,
        
        timeline=
        {
            TimeEvent(9*FRAMES, function(inst) inst:PerformBufferedAction()  end),
            TimeEvent(12*FRAMES, function(inst) inst.sg:RemoveStateTag("busy") inst.sg:AddStateTag("idle") end),
        },        
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ),
        },        
    },
	State{
        name = "hit",
        tags = {"hit", "busy"},
        
        onenter = function(inst, cb)
            if inst.components.locomotor then
                inst.components.locomotor:StopMoving()
            end
            inst.AnimState:PlayAnimation("hit")
            if inst.SoundEmitter and inst.sounds then
                if inst.sounds.hit then
                    inst.SoundEmitter:PlaySound(inst.sounds.hit)
                end
            end
        end,
		
		timeline = {TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/hurt_beaver") end)},
        
        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
    State{
        name = "attack",
        tags = { "attack", "notalking", "abouttoattack" },

        onenter = function(inst)
			--print(debugstack())
            inst.sg.statemem.action = inst:GetBufferedAction()
            local target = inst.sg.statemem.action ~= nil and inst.sg.statemem.action.target or nil
            inst.components.combat:SetTarget(target)
            inst.components.combat:StartAttack()
            inst.components.locomotor:Stop()
            -- local cooldown = inst.components.combat.min_attack_period + .5 * FRAMES

                inst.AnimState:PlayAnimation("atk")
                -- cooldown = math.max(cooldown, 24 * FRAMES)

            -- inst.sg:SetTimeout(cooldown)

            if target ~= nil then
                -- inst.components.combat:BattleCry()
                if target:IsValid() then
                    inst:FacePoint(target:GetPosition())
                end
            end
        end,

		timeline = 
		{
		
			TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh") end),
			-- TimeEvent(6*FRAMES, function(inst) inst.components.combat:DoAttack(inst.sg.statemem.target) end),
			TimeEvent(6*FRAMES, function(inst) inst:PerformBufferedAction() end),
			TimeEvent(8*FRAMES, function(inst) inst.sg:RemoveStateTag("attack") inst.sg:RemoveStateTag("busy") inst.sg:AddStateTag("idle") end),
		},
        -- timeline =
        -- {
            -- TimeEvent(8 * FRAMES, function(inst)
                -- inst:PerformBufferedAction()
                -- inst.sg:RemoveStateTag("abouttoattack")
            -- end),
        -- },

        -- ontimeout = function(inst)
            -- inst.sg:RemoveStateTag("attack")
            -- if inst.components.playercontroller ~= nil and
                -- inst.components.playercontroller:IsAnyOfControlsPressed(
                    -- CONTROL_PRIMARY,
                    -- CONTROL_ATTACK,
                    -- CONTROL_CONTROLLER_ATTACK) and
                -- inst.sg.statemem.weapon == inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) then
                -- local target = inst.components.combat.target
                -- if target ~= nil and
                    -- target:IsValid() and
                    -- target.components.health ~= nil and
                    -- target.components.combat ~= nil and
                    -- inst.components.combat ~= nil and
                    -- not target.components.health:IsDead() and
                    -- target.components.combat:CanBeAttacked(inst) and
                    -- inst.components.combat:CanHitTarget(target, inst.sg.statemem.weapon) then
                    -- inst:PushBufferedAction(inst.sg.statemem.action)
                -- end
            -- end
        -- end,

        events =
        {
            EventHandler("animqueueover", function(inst)
                if inst.AnimState:AnimDone() then
                    inst.sg:GoToState("idle")
                end
            end),
        },

        onexit = function(inst)
            inst.components.combat:SetTarget(nil)
        end,
    },
	State{
		name = "death",  
        tags = {"busy"},
        
        onenter = function(inst)
            inst.AnimState:PlayAnimation("death")
            if inst.components.locomotor then
                inst.components.locomotor:StopMoving()
            end
			inst.Physics:ClearCollisionMask()
            inst.components.lootdropper:DropLoot(Vector3(inst.Transform:GetWorldPosition()))            
        end,
		
		timeline = {}
    }
}

-- CommonStates.AddCombatStates(states,
-- {
    -- hittimeline =
    -- {
        -- TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/hurt_beaver") end),
    -- },
    
    -- attacktimeline = 
    -- {
    
        -- TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh") end),
        -- TimeEvent(6*FRAMES, function(inst) inst.components.combat:DoAttack(inst.sg.statemem.target) end),
        -- TimeEvent(8*FRAMES, function(inst) inst.sg:RemoveStateTag("attack") inst.sg:RemoveStateTag("busy") inst.sg:AddStateTag("idle") end),
    -- },

    -- deathtimeline=
    -- {
    -- },
-- })

CommonStates.AddRunStates(states,
{
	runtimeline = {
		TimeEvent(0*FRAMES, PlayFootstep ),
		TimeEvent(10*FRAMES, PlayFootstep ),
	},
})

CommonStates.AddIdle(states)
    
return StateGraph("werebeaver", states, events, "idle", actionhandlers)

