require("stategraphs/commonstates")

local actionhandlers = 
{
    ActionHandler(ACTIONS.CHOP, "chop"),
    ActionHandler(ACTIONS.MINE, "mine"),
    ActionHandler(ACTIONS.PICKUP, "pickup"),
    ActionHandler(ACTIONS.GIVE, "give"),
    ActionHandler(ACTIONS.PICK, "pick"),
	ActionHandler(ACTIONS.EAT, "quickeat"),
}

local function DoTalkSound(inst)
    if table.contains(CHARACTER_GENDERS.FEMALE, inst.charanm) then
        inst.SoundEmitter:PlaySound("dontstarve/characters/willow/talk_LP", "talk")
    else
        inst.SoundEmitter:PlaySound("dontstarve/characters/wilson/talk_LP", "talk")
    end
    return true
end

   
local events=
{
    CommonHandlers.OnLocomote(true, false),
    EventHandler("doattack", 
    function(inst, data) 
        if not inst.components.health:IsDead() then
            inst.sg:GoToState("attack", data.target) 
            if data.target and data.target.components.combat and data.target:HasTag("wall") then
                inst.components.talker:Say("walls cannot prevent me !")
                data.target.components.combat:GetAttacked(inst, 75) 
            end
        end 
    end),
    EventHandler("death", function(inst)
        inst.components.talker:Say("This is impossible!")
        inst.sg:GoToState("death")
        if inst.fx then
            if inst.fx.task then
                inst.fx.task:Cancel()
                inst.fx.task=nil
            end
            inst.fx:Remove()
            inst.fx=nil
        end
    end),

    EventHandler("attacked", function(inst, data)
        if not inst.components.health:IsDead() and math.random()<0.6 and not inst:HasTag('protected') then
            inst.sg:GoToState("hit")
            inst:AddTag('protected')
            if not inst.protectedtask then
                inst.protectedtask=inst:DoTaskInTime(1, function() 
                    if inst:HasTag('protected') then
                        inst:RemoveTag('protected')
                    end
                    if inst.protectedtask then
                        inst.protectedtask:Cancel()
                        inst.protectedtask=nil
                    end
                end)
            end
        end
    end),

}

local states= 
{

    State{
        name = "death",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.components.locomotor:Stop()
            inst.AnimState:Hide("swap_arm_carry")
            inst.AnimState:PlayAnimation("death")
            inst.components.lootdropper:DropLoot(Vector3(inst.Transform:GetWorldPosition())) 
            local x, y, z = inst.Transform:GetWorldPosition() 
            if not inst.onwater and math.random()<0.2 then
                shitswap("skeleton").Transform:SetPosition(x, y, z)
            end
            if inst.berry then
                shitswap("dug_"..inst.berry).Transform:SetPosition(x, y, z)
            end
        end,
    },

    State{
        name = "idle",
        tags = {"idle", "canrotate"},
        onenter = function(inst, pushanim) 
            inst.components.locomotor:Stop()
            local anims = {"idle_loop"}          
            local anim = "idle_loop"                      
            if pushanim then
                for k,v in pairs (anims) do
					inst.AnimState:PushAnimation(v, k == #anims)
				end
            else
                inst.AnimState:PlayAnimation(anims[1], #anims == 1)
                for k,v in pairs (anims) do
					if k > 1 then
						inst.AnimState:PushAnimation(v, k == #anims)
					end
				end
            end  
            inst.sg:SetTimeout(math.random()*4+2)
        end,
    },

    State{
        name = "quickeat",
        tags ={"busy"},
        onenter = function(inst)
            inst.components.locomotor:Stop()
            inst.AnimState:PlayAnimation("quick_eat")
        end,

        timeline=
        {
            TimeEvent(12*FRAMES, function(inst) 
                inst:PerformBufferedAction() 
                inst.sg:RemoveStateTag("busy")
            end),
        },        
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
        
        onexit= function(inst)
            inst.SoundEmitter:KillSound("eating")    
        end,
    },    
	
	State{
        name = "attack",
        tags = {"attack", "notalking", "abouttoattack", "busy"},
        
        onenter = function(inst)
            inst.sg.statemem.target = inst.components.combat.target
            inst.components.combat:StartAttack()
            inst.components.locomotor:Stop()
            if inst.myweapon == "swap_blowdart" then
                inst.AnimState:PlayAnimation("dart")
            else
                inst.AnimState:PlayAnimation("atk")  
            end
        end,
        
        timeline=
        {	
			TimeEvent(4*FRAMES, function(inst)
                inst.SoundEmitter:PlaySound("dontstarve/tentacle/tentacle_attack")
            end),
            TimeEvent(8*FRAMES, function(inst)
                inst.sg:RemoveStateTag("abouttoattack")
                inst.components.combat:DoAttack(inst.sg.statemem.target)
                inst.sg:RemoveStateTag("busy")
				inst.sg:RemoveStateTag("attack")
            end),   
        },
        
        events=
        {
            EventHandler("animover", function(inst)
                inst.sg:GoToState("idle")
            end ),
        },
    },    
   
    State{
        name = "run_start",
        tags = {"moving", "running", "canrotate"},
        
        onenter = function(inst)
			inst.components.locomotor:RunForward()
            if inst.onwater then
                inst.AnimState:PlayAnimation("row_pre")
            else
                inst.AnimState:PlayAnimation("run_pre")
            end
            inst.sg.mem.foosteps = 0
        end,

        onupdate = function(inst)
            inst.components.locomotor:RunForward()
        end,

        events=
        {   
            EventHandler("animover", function(inst) inst.sg:GoToState("run") end ),        
        },
        
        timeline=
        {
        
            TimeEvent(4*FRAMES, function(inst)
                PlayFootstep(inst)
            end),
        },        
        
    },

    State{
        name = "run",
        tags = {"moving", "running", "canrotate"},
        
        onenter = function(inst) 
            inst.components.locomotor:RunForward()
            if inst.onwater then
                inst.AnimState:PlayAnimation("row_loop")
            else
                inst.AnimState:PlayAnimation("run_loop")
            end
        end,
        
        onupdate = function(inst)
            inst.components.locomotor:RunForward()
        end,

        timeline=
        {
            TimeEvent(7*FRAMES, function(inst)
				inst.sg.mem.foosteps = inst.sg.mem.foosteps + 1
                PlayFootstep(inst, inst.sg.mem.foosteps < 5 and 1 or .6)
            end),
            TimeEvent(15*FRAMES, function(inst)
				inst.sg.mem.foosteps = inst.sg.mem.foosteps + 1
                PlayFootstep(inst, inst.sg.mem.foosteps < 5 and 1 or .6)
            end),
        },
        
        events=
        {   
            EventHandler("animover", function(inst) inst.sg:GoToState("run") end ),        
        },
    },
    
    State{
        name = "run_stop",
        tags = {"canrotate", "idle"},
        
        onenter = function(inst) 
            inst.components.locomotor:Stop()
            inst.AnimState:PlayAnimation("run_pst")
        end,
        
        events=
        {   
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ),        
        },       
    }, 

    State{
        name = "hit",
        tags = {"busy"},
        onenter = function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/hit") 
            if table.contains(CHARACTER_GENDERS.FEMALE, inst.charanm) then
                inst.SoundEmitter:PlaySound("dontstarve/characters/willow/hurt") 
            else
                inst.SoundEmitter:PlaySound("dontstarve/characters/wilson/hurt") 
            end
                   
            inst.AnimState:PlayAnimation("hit")
            inst:ClearBufferedAction()
            inst.components.locomotor:Stop()            
        end,
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ),
        }, 
        
        timeline =
        {
            TimeEvent(3*FRAMES, function(inst)
                inst.sg:RemoveStateTag("busy")
            end),
        },        
               
    },   

    State{
        name = "talk",
        tags = { "idle", "talking" },

        onenter = function(inst, noanim)
            if not noanim then
                inst.AnimState:PlayAnimation("dial_loop", true)
            end
            DoTalkSound(inst)
            inst.sg:SetTimeout(1.5 + math.random() * .5)
        end,

        ontimeout = function(inst)
            inst.sg:GoToState("idle")
        end,

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

        onexit = function(inst)
            inst.SoundEmitter:KillSound("talk")
        end,
    },

        State{
            name = "wakeup",
            tags = {"busy"},
            onenter = function(inst)
                inst.AnimState:PlayAnimation("wakeup")
            end,
            onexit = function(inst)
            end,
            events=
            {
                EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
            },
            timeline =
            {
                TimeEvent(80*FRAMES, function(inst)
                    if inst.components.combat then
                        inst.components.combat:SetTarget(GetPlayer())
                    end
                    if inst.components.talker then
                        inst.components.talker:Say("Surprise!")
                    end
                    inst.sg:RemoveStateTag("busy")
                end),
            },
        },

            State{
                name = "eat",
                tags = { "busy" },

                onenter = function(inst, feed)
                    inst.components.locomotor:Stop()
                    inst.SoundEmitter:PlaySound("dontstarve/wilson/eat", "eating")
                    inst.AnimState:PlayAnimation("eat")
                end,

                timeline =
                {
                    TimeEvent(12 * FRAMES, function(inst)
                        inst.sg:RemoveStateTag("busy")
                        inst.sg:RemoveStateTag("pausepredict")
                    end),
                },

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

                onexit = function(inst)
                    inst.SoundEmitter:KillSound("eating")
                end,
            },
            State{
            name = "give",
            tags = { "giving" },

            onenter = function(inst)
                inst.components.locomotor:Stop()
                inst.AnimState:PlayAnimation("give")
                inst.sg:SetTimeout(6*FRAMES)
            end,

            timeline =
            {
            },
            ontimeout = function(inst)
                inst.sg:GoToState("idle")
            end,
        },

        State{
            name = "jumpin",
            tags = {"busy"},
            onenter = function(inst)
                inst.AnimState:PlayAnimation("jump")
                inst:DoTaskInTime(3, function(inst) 
                    inst.SoundEmitter:PlaySound("dontstarve/movement/bodyfall_dirt", "bodyfall") 
                    inst.AnimState:PlayAnimation("idle")
                end )
            end,
            timeline =
            {
                TimeEvent(15*FRAMES, function(inst) 
                    inst.components.combat:SetTarget(GetPlayer())
                    if inst.components.talker then
                        inst.components.talker:Say("surprise!")
                    end
                    inst.sg:RemoveStateTag("busy") 
                end),
            },
            onexit = function(inst)
            end,
            events=
            {
                EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
            },
        },

    }

    
return StateGraph("SGrivenmember", states, events, "idle", actionhandlers)

