require("stategraphs/commonstates")

function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end

local actionhandlers = 
{
    ActionHandler(ACTIONS.GOHOME, "graze"),
	ActionHandler(ACTIONS.ATTACK, "attack"),
	ActionHandler(ACTIONS.PICKUP, "graze_empty"),
	ActionHandler(ACTIONS.DROP, "regurgitate"),
	ActionHandler(ACTIONS.EAT, "graze"),
	ActionHandler(ACTIONS.HEAL, "graze"),
	ActionHandler(ACTIONS.FAN, "wake"),
	ActionHandler(ACTIONS.SLEEPIN, "sleep"),
	ActionHandler(ACTIONS.PICK, "graze_empty"),
	ActionHandler(ACTIONS.FEED, "regurgitate"),
	ActionHandler(ACTIONS.GIVE, "regurgitate"),
	ActionHandler(ACTIONS.GIVETOPLAYER, "regurgitate"),
	ActionHandler(ACTIONS.GIVEALLTOPLAYER, "regurgitate"),
	ActionHandler(ACTIONS.JUMPIN, "eat"),
	ActionHandler(ACTIONS.TRAVEL, "eat"),
	ActionHandler(ACTIONS.MIGRATE, "eat"),
	ActionHandler(ACTIONS.COMBINESTACK, "graze"),
	ActionHandler(ACTIONS.UNWRAP, "graze"),	
}

local mobCraftActions =
{
	ActionHandler(ACTIONS.GOHOME, "gohome"),
	ActionHandler(ACTIONS.ATTACK, "attack"),
	ActionHandler(ACTIONS.PICKUP, "graze_empty"),
	ActionHandler(ACTIONS.PICK, "graze"),
	ActionHandler(ACTIONS.INVESTIGATE, "graze_empty"),
	ActionHandler(ACTIONS.DROP, "regurgitate"),
	ActionHandler(ACTIONS.SLEEPIN, "home"),
	ActionHandler(ACTIONS.EAT, "graze"),
	ActionHandler(ACTIONS.HEAL, "graze"),
	ActionHandler(ACTIONS.ACTIVATE, "graze"),	
	ActionHandler(ACTIONS.FAN, "graze"),
	ActionHandler(ACTIONS.DIG, "graze"),
	ActionHandler(ACTIONS.CHOP, "attack"),
	ActionHandler(ACTIONS.MINE, "attack"),
	ActionHandler(ACTIONS.COOK, "graze"),
	ActionHandler(ACTIONS.FILL, "graze"),
	ActionHandler(ACTIONS.DRY, "graze"),
	ActionHandler(ACTIONS.ADDFUEL, "graze"),
	ActionHandler(ACTIONS.ADDWETFUEL, "graze"),
	ActionHandler(ACTIONS.LIGHT, "graze"),
	ActionHandler(ACTIONS.BAIT, "graze"),
	ActionHandler(ACTIONS.BUILD, "graze"),
	ActionHandler(ACTIONS.PLANT, "graze"),
	ActionHandler(ACTIONS.REPAIR, "graze"),
	ActionHandler(ACTIONS.HARVEST, "graze"),
	ActionHandler(ACTIONS.STORE, "graze"),
	ActionHandler(ACTIONS.RUMMAGE, "graze"),
	ActionHandler(ACTIONS.DEPLOY, "graze"),
	ActionHandler(ACTIONS.HAMMER, "attack"),
	ActionHandler(ACTIONS.FERTILIZE, "graze"),
	ActionHandler(ACTIONS.MURDER, "graze"),
	ActionHandler(ACTIONS.UNLOCK, "graze"),
	ActionHandler(ACTIONS.TURNOFF, "graze"),
	ActionHandler(ACTIONS.TURNON, "graze"),
	ActionHandler(ACTIONS.SEW, "graze"),
	ActionHandler(ACTIONS.COMBINESTACK, "graze"),
	ActionHandler(ACTIONS.UPGRADE, "graze"),
	ActionHandler(ACTIONS.WRITE, "graze"),
	ActionHandler(ACTIONS.FEEDPLAYER, "graze"),
	ActionHandler(ACTIONS.TERRAFORM, "graze"),
	ActionHandler(ACTIONS.NET, "attack"),
	ActionHandler(ACTIONS.CHECKTRAP, "graze"),
	ActionHandler(ACTIONS.SHAVE, "graze"),
	ActionHandler(ACTIONS.FISH, "graze"),
	ActionHandler(ACTIONS.REEL, "graze"),
	ActionHandler(ACTIONS.CATCH, "graze"),
	ActionHandler(ACTIONS.TEACH, "graze"),
	ActionHandler(ACTIONS.MANUALEXTINGUISH, "graze"),
	ActionHandler(ACTIONS.RESETMINE, "graze"),
	ActionHandler(ACTIONS.BLINK, "graze"),
	ActionHandler(ACTIONS.FEED, "regurgitate"),
	ActionHandler(ACTIONS.GIVE, "regurgitate"),
	ActionHandler(ACTIONS.GIVETOPLAYER, "regurgitate"),
	ActionHandler(ACTIONS.GIVEALLTOPLAYER, "regurgitate"),
	--ActionHandler(ACTIONS.CHANGEIN, "changeskin"),
	ActionHandler(ACTIONS.SMOTHER, "graze"),
	ActionHandler(ACTIONS.CASTSPELL, "graze"),
	---PetActions--
	ActionHandler(ACTIONS.PET, "graze"),
	ActionHandler(ACTIONS.ABANDON, "graze"),
	ActionHandler(ACTIONS.WRAPBUNDLE, "graze"),
	ActionHandler(ACTIONS.UNWRAP, "graze"),
	ActionHandler(ACTIONS.UNLOCK, "graze"),
	ActionHandler(ACTIONS.USEKLAUSSACKKEY, "graze"),
}


local extraActions = 
{
	--ActionHandler(ACTIONS.SLEEPIN, "sleep"),
	ActionHandler(ACTIONS.TRAVEL, "taunt"),
	ActionHandler(ACTIONS.LOOKAT, "taunt"),
}

if MOBCRAFT == "Enable" then
	extraActions = mobCraftActions
end

actionhandlers = TableConcat(actionhandlers, extraActions)

local events=
{
    EventHandler("attacked", function(inst) if not inst.components.health:IsDead() and not inst.sg:HasStateTag("attack") then inst.sg:GoToState("hit") end end),
    EventHandler("death", function(inst) inst.sg:GoToState("death") end),
    EventHandler("doattack", function(inst, data) if not inst.components.health:IsDead() and (inst.sg:HasStateTag("hit") or not inst.sg:HasStateTag("busy")) then inst.sg:GoToState("attack", data.target) end end),
    CommonHandlers.OnSleep(),
    CommonHandlers.OnLocomote(true,false),
    CommonHandlers.OnFreeze(),
	
	 EventHandler("ms_opengift",
        function(inst)
            if not inst.sg:HasStateTag("busy") then
                inst.sg:GoToState("opengift")
            end
        end),
}


 local states=
{

	State{
        name = "opengift",
        tags = { "busy", "pausepredict" },

        onenter = function(inst)
            inst.components.locomotor:Stop()
            inst.components.locomotor:Clear()
            inst:ClearBufferedAction()

            --if IsNearDanger(inst) then
                --inst.sg.statemem.isdanger = true
                --inst.sg:GoToState("idle")
                --if inst.components.talker ~= nil then
                   -- inst.components.talker:Say(GetString(inst, "ANNOUNCE_NODANGERGIFT"))
                --end
                --return
           -- end

            inst.SoundEmitter:PlaySound("dontstarve/common/player_receives_gift")
            inst.AnimState:PlayAnimation("idle_loop", true)
            --inst.AnimState:PushAnimation("idle_loop", true)
            -- NOTE: the previously used ripping paper anim is called "giift_loop"

            if inst.components.playercontroller ~= nil then
                inst.components.playercontroller:RemotePausePrediction()
                inst.components.playercontroller:EnableMapControls(false)
                inst.components.playercontroller:Enable(false)
            end
            inst.components.inventory:Hide()
            inst:PushEvent("ms_closepopups")
            inst:ShowActions(false)
            inst:ShowGiftItemPopUp(true)

            if inst.components.giftreceiver ~= nil then
                inst.components.giftreceiver:OnStartOpenGift()
            end
        end,

        timeline =
        {
            -- Timing of the gift box opening animation on giftitempopup.lua
            TimeEvent(155 * FRAMES, function(inst)
               -- inst.AnimState:PlayAnimation("gift_open_pre")
                inst.AnimState:PushAnimation("idle_loop", true)
            end),
        },

        events =
        {
            EventHandler("firedamage", function(inst)
                inst.AnimState:PlayAnimation("idle_loop")
                inst.sg:GoToState("idle", true)
                if inst.components.talker ~= nil then
                    inst.components.talker:Say(GetString(inst, "ANNOUNCE_NODANGERGIFT"))
                end
            end),
            EventHandler("ms_doneopengift", function(inst, data)
                inst.sg:GoToState("idle", true)
            end),
        },

        onexit = function(inst)
            if inst.sg.statemem.isdanger then
                return
            elseif not inst.sg.statemem.isopeningwardrobe then
                if inst.components.playercontroller ~= nil then
                    inst.components.playercontroller:EnableMapControls(true)
                    inst.components.playercontroller:Enable(true)
                end
                inst.components.inventory:Show()
                inst:ShowActions(true)
            end
            inst:ShowGiftItemPopUp(false)
        end,
    },

	State {
        name = "sleep",
        tags = { "sleeping" }, --add tag "busy" if you hate sliding

        onenter = function(inst)
            if inst.components.locomotor ~= nil then
                inst.components.locomotor:StopMoving()
            end
            inst.AnimState:PlayAnimation("sleep_pre")
            --if fns ~= nil and fns.onsleep ~= nil then
                --fns.onsleep(inst)
            --end
        end,

        --timeline = timelines ~= nil and timelines.starttimeline or nil,

        events =
        {
            EventHandler("animqueueover", function(inst) inst.sg:GoToState("sleeping") end ),
            EventHandler("onwakeup", function(inst) inst.sg:GoToState("wake") end),
        },
    },

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

        --onenter = onentersleeping,
		
		onenter = function(inst)
				inst.components.locomotor:StopMoving()
				local hungerpercent = inst.components.hunger:GetPercent()
				if hungerpercent ~= nil and hungerpercent ~= 0 then -- We don't want players to heal out starvation.
				inst.components.health:DoDelta(20, false)
				end
				--inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/bearger/sleep")
				inst.AnimState:PlayAnimation("sleep_loop")
			end,

        --timeline = timelines ~= nil and timelines.sleeptimeline or nil,
		timeline=
        {
			TimeEvent(46*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.grunt) end),
        },

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

    State
    {
        name = "wake",
        tags = { "busy", "waking" },

        onenter = function(inst)
            if inst.components.locomotor ~= nil then
                inst.components.locomotor:StopMoving()
            end
            inst.AnimState:PlayAnimation("sleep_pst")
            if inst.components.sleeper ~= nil and inst.components.sleeper:IsAsleep() then
                inst.components.sleeper:WakeUp()
            end
            --if fns ~= nil and fns.onwake ~= nil then
                --fns.onwake(inst)
            --end
        end,

        --timeline = timelines ~= nil and timelines.waketimeline or nil,

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
	
	State{
        name = "idle",
        tags = {"idle", "canrotate"},
        
        onenter = function(inst, pushanim)
            --inst.components.locomotor:StopMoving()
            if inst.hairGrowthPending then
                inst.sg:GoToState("hair_growth")
            elseif inst.growUpPending then
                inst.sg:GoToState("grow_up")
            elseif inst.domesticationPending then
                inst.sg:GoToState("become_domesticated")
            else
                
                inst.AnimState:PlayAnimation("idle_loop", true)
                
                
                inst.sg:SetTimeout(1 + 1*math.random())
            end
        end,
    },
    
    State{
        name = "shake",
        tags = {"idle", "canrotate"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("shake")
			inst:PerformBufferedAction()
        end,
       
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
    
    State{
        name = "shake_off_saddle",
        tags = {"busy"},

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("shakesaddle_off")
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/saddle/shake_off")
        end,

        timeline=
        {
            --TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            --TimeEvent(5*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            --TimeEvent(9*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            --TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            --TimeEvent(20*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            TimeEvent(24*FRAMES, function(inst) inst.components.rideable:SetSaddle(nil, nil) end),
        },

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

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("vomit")
            --inst.SoundEmitter:PlaySound("dontstarve/beefalo/puke_start")
        end,

        timeline=
        {
            TimeEvent(14*FRAMES, function(inst)
                inst.SoundEmitter:PlaySound("dontstarve/beefalo/puke_out")
				inst:PerformBufferedAction()
                --local loot = SpawnPrefab("spoiled_food")
                --local x,y,z = inst.Transform:GetWorldPosition()
                --==loot.Transform:SetPosition(x, 1.0, z)
                --loot.components.inventoryitem:AddMoisture(50)
            end),
        },

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

	State{
        name = "special_atk2",
        tags = {"busy"},
        
        onenter = function(inst)
            if inst.specialatk == false then
				inst.sg:GoToState("idle")
			else
				inst.sg:GoToState("breeding")
			end
        end,

		onexit = function(inst)
            
			--if inst.components.timer:TimerExists(SpecialTimer) then
            --inst.components.timer:StartTimer(SpecialTimer, 10)
			--end
        end,
		
		timeline=
        {
           
        },
		
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
	
	State{
        name = "breeding",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("bellow")
			inst.AnimState:PlayAnimation("hit")
            inst.SoundEmitter:PlaySound(inst.sounds.grunt)
			inst.specialatk = false
			
        end,
		
		timeline=
		{
			TimeEvent(10*FRAMES, function(inst) inst:PerformBufferedAction() end),
			TimeEvent(10*FRAMES, function(inst)
                local baby = SpawnPrefab("babybeefalo")
				local pos = inst:GetPosition()
				baby.Transform:SetPosition(pos:Get())
				inst.components.leader:AddFollower(baby)
				
            end),
		},
		
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") inst:DoTaskInTime(8640, function() inst.specialatk = true end) end),
        },
    },
	
    State{
        name = "bellow",
        tags = {"canrotate"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("bellow")
            inst.SoundEmitter:PlaySound(inst.sounds.grunt)
        end,
       
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
    
	State{
        name = "special_atk1",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("bellow")
            inst.SoundEmitter:PlaySound(inst.sounds.grunt)
        end,
       
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
	
    State{
        name = "matingcall",
        tags = {"busy"},
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("mating_taunt1")
            inst.SoundEmitter:PlaySound(inst.sounds.yell)
        end,
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
	
	 State{
        name = "rage",
        tags = {},
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("mating_taunt1")
            inst.SoundEmitter:PlaySound(inst.sounds.yell)
        end,
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
    
    
    State{
        name = "tailswish",
        tags = {},
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("mating_taunt2")
        end,
        
        timeline=
        {
            TimeEvent(22*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
            TimeEvent(32*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.swish) end),
        },
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },
    
    State{
        name="graze",
        tags = {"canrotate"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
			inst:PerformBufferedAction()
            inst.AnimState:PlayAnimation("graze_loop", true)
            inst.sg:SetTimeout(0.5)
        end,
        
        ontimeout= function(inst)
            inst.sg:GoToState("idle")
        end,

    },

    State{
        name="graze_empty",
        tags = {"canrotate"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("graze2_pre")
			
            inst.AnimState:PushAnimation("graze2_loop")
			
            inst.sg:SetTimeout(1)
        end,
        
        ontimeout= function(inst)
			inst:PerformBufferedAction()
            inst.AnimState:PlayAnimation("graze2_pst")
            inst.sg:GoToState("idle", true)
        end,

    },

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("graze_loop", true)
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/eat_treat")
            inst.sg:SetTimeout(0.5)
			inst:PerformBufferedAction()
        end,

        timeline =
        {
            TimeEvent(14*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/beefalo/chew") end),
            --TimeEvent(56*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/beefalo/chew") end),
            --TimeEvent(84*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/beefalo/chew") end),
            --TimeEvent(112*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/beefalo/chew") end),
        },

        ontimeout= function(inst)
            if inst.sg.statemem.full then
                inst.sg:GoToState("regurgitate")
            else
                inst.sg:GoToState("idle")
            end
        end,

    },
    
    State{
        name = "alert",
        tags = {"idle", "canrotate"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            if not inst.didalertnoise then
                inst.SoundEmitter:PlaySound(inst.sounds.curious)
                inst.didalertnoise = true
            end
            if not inst.AnimState:IsCurrentAnimation("alert_idle") then
                inst.AnimState:PlayAnimation("alert_pre")
                inst.AnimState:PushAnimation("alert_idle", true)
            end

            inst.sg:SetTimeout(2 + 2*math.random())
        end,
        
        ontimeout=function(inst)
            if inst.components.rideable and inst.components.rideable:IsSaddled() and inst.components.domesticatable and inst.components.domesticatable:GetObedience() < TUNING.BEEFALO_KEEP_SADDLE_OBEDIENCE then
                inst.sg:GoToState("shake_off_saddle")
            elseif inst.domesticationPending then
                inst.sg:GoToState("become_domesticated")
            else
                inst.sg:GoToState("alert")
            end
        end,
    },

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

        onenter = function(inst, target)
            inst.sg.statemem.target = target
            inst.SoundEmitter:PlaySound(inst.sounds.angry)
            inst.components.combat:StartAttack()
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("atk_pre")
            inst.AnimState:PushAnimation("atk", false)
        end,

        timeline=
        {
            TimeEvent(15*FRAMES, function(inst) inst:PerformBufferedAction() end),
        },

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

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

        onenter = function(inst)
            inst.SoundEmitter:PlaySound(inst.sounds.yell)
            inst.AnimState:PlayAnimation("death")
            inst.Physics:Stop()
            RemovePhysicsColliders(inst)
			
            inst.components.lootdropper:DropLoot(inst:GetPosition())
			inst.components.inventory:DropEverything(true)

            if inst.components.playercontroller ~= nil then
                inst.components.playercontroller:RemotePausePrediction()
            end
        end,

        events =
        {
            EventHandler("animover", function(inst)
                if inst.AnimState:AnimDone() then
                    if MOBGHOST == "Enable" then
                     inst:PushEvent(inst.ghostenabled and "makeplayerghost" or "playerdied", { skeleton = false })
					else
						TheWorld:PushEvent("ms_playerdespawnanddelete", inst)
					end
                end
            end),
        },
    },

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("transform") 
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/hairgrow_pop")
            inst.domesticationPending = false
        end,

        timeline=
        {
            TimeEvent(8*FRAMES, function(inst) SpawnPrefab("beefalo_transform_fx").Transform:SetPosition(inst.Transform:GetWorldPosition()) end),
            TimeEvent(11*FRAMES, function(inst) inst:UpdateDomestication() end),
        },

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

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("hair_growth_pre")
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/hairgrow_vocal")
        end,

        events=
        {
            EventHandler("animover", function(inst)
                inst.components.growable:SetStage(inst.components.growable:GetNextStage())
                inst.growUpPending = false
                inst.sg:GoToState("grow_up_pop")
            end),
        },
    },

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("hair_growth")
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/hairgrow_pop")
        end,

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


    State{
        name = "hair_growth",
        tags = {"busy"},
        
        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("hair_growth_pre")
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/hairgrow_vocal")
        end,
        
        events=
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("hair_growth_pop") end),
        },
    },

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

        onenter = function(inst)
            inst.components.locomotor:StopMoving()
            inst.AnimState:PlayAnimation("hair_growth")
            inst.SoundEmitter:PlaySound("dontstarve/beefalo/hairgrow_pop")
            if inst.components.beard then
                    inst.AnimState:SetBuild("beefalo_build")
                inst.components.beard.bits = 3
            end
            inst.hairGrowthPending = false
            inst:ApplyBuildOverrides(inst.AnimState)
        end,

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

    State{
        name = "shaved",
        tags = {"busy", "sleeping"},
        
        onenter = function(inst)
            inst:ApplyBuildOverrides(inst.AnimState)
            inst.AnimState:PlayAnimation("shave")
        end,
        
        events=
        {
            EventHandler("animover", function(inst)
                if inst.components.sleeper and inst.components.sleeper:IsAsleep() then
                    inst.sg:GoToState("sleeping")
                else
                    inst.sg:GoToState("wake")
                end
            end),
        },
    },
	
	State
    {
        name = "run_start",
        tags = { "moving", "running", "canrotate" },

        onenter = function(inst)
		if inst:HasTag("runner") then --convert that into a variable to avoid tag issues.
            inst.components.locomotor:WalkForward()
            inst.AnimState:PlayAnimation("walk_pre")
			else			
			inst.components.locomotor:RunForward()
            inst.AnimState:PlayAnimation("run_pre")
			end
        end,

        events =
        {
            EventHandler("animqueueover", function(inst) inst.sg:GoToState("run") end ),
        },
    },
	
	State
    {
        name = "run",
        tags = { "moving", "running", "canrotate" },

        onenter = function(inst)
			if inst:HasTag("runner") then
            inst.components.locomotor:WalkForward()
			inst.AnimState:PlayAnimation("walk_loop")
			else			
			inst.components.locomotor:RunForward()
            inst.AnimState:PlayAnimation("run_loop")
			end
        end,
		
		timeline =
        {
            TimeEvent(1*FRAMES, function(inst) inst.didalertnoise = nil end),
            TimeEvent(5*FRAMES, PlayFootstep),
        },
		
        events=
			{
				EventHandler("animqueueover", function(inst) inst.sg:GoToState("run") end ),
			},

    },
	
	State
    {
        name = "run_stop",
        tags = { "idle" },

        onenter = function(inst) 
            inst.components.locomotor:StopMoving()
            if inst:HasTag("runner") then			
			inst.AnimState:PlayAnimation("walk_pst")
			else
			inst.AnimState:PlayAnimation("run_pst")
			end
            
        end,


        events =
        {
            EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end ),
        },
    },
	
    State{
        name = "refuse",
        tags = {"busy"},

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

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


--[[CommonStates.AddSleepStates(states,
{
	sleeptimeline = {
        TimeEvent(30*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/hound/sleep") end),
	},
})

]]

CommonStates.AddWalkStates(
    states,
    {
        walktimeline =
        {
            TimeEvent(1*FRAMES, function(inst) inst.didalertnoise = nil end),
            TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.walk) end),
            TimeEvent(40*FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.walk) end),
        }
    })
    
--CommonStates.AddRunStates(
    --states,
    --{
        --runtimeline =
        --{
            --TimeEvent(1*FRAMES, function(inst) inst.didalertnoise = nil end),
            --TimeEvent(5*FRAMES, PlayFootstep),
        --}
    --})

CommonStates.AddSimpleState(states,"hit", "hit")
CommonStates.AddFrozenStates(states)
    



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

