local MakePlayerCharacter = require "prefabs/player_common"

local assets = 
{
	Asset("ANIM", "anim/beefalo_basic.zip"),
    Asset("ANIM", "anim/beefalo_actions.zip"),
    Asset("ANIM", "anim/beefalo_actions_domestic.zip"),
    Asset("ANIM", "anim/beefalo_build.zip"),
    Asset("ANIM", "anim/beefalo_shaved_build.zip"),
    Asset("ANIM", "anim/beefalo_baby_build.zip"),

	Asset("ANIM", "anim/beefalo_shiny_build_01.zip"),
	
    Asset("ANIM", "anim/beefalo_domesticated.zip"),
    Asset("ANIM", "anim/beefalo_personality_docile.zip"),
    Asset("ANIM", "anim/beefalo_personality_ornery.zip"),
    Asset("ANIM", "anim/beefalo_personality_pudgy.zip"),

    Asset("ANIM", "anim/beefalo_fx.zip"),

    Asset("SOUND", "sound/beefalo.fsb"),
	--Asset("ANIM", "anim/ghost_waxwell_build.zip"),
}

local prefabs = {	
    }
local start_inv = {
	"beefalowool",
	"beefalowool",
	"beefalowool",
	"beefalowool",
	"monster_wpn",
}

SetSharedLootTable( 'beefplayer',
{
	{'meat',			 1.00},
	{'meat',			 1.00},
	{'meat',			 1.00},
	{'meat',			 1.00},
	{'beefalowool',     1.00},
    {'beefalowool',     1.00},
    {'beefalowool',     1.00},
    {'horn',            0.33},
	
	
})

local sounds = 
{
    walk = "dontstarve/beefalo/walk",
    grunt = "dontstarve/beefalo/grunt",
    yell = "dontstarve/beefalo/yell",
    swish = "dontstarve/beefalo/tail_swish",
    curious = "dontstarve/beefalo/curious",
    angry = "dontstarve/beefalo/angry",
}




local function Equip(inst)
    local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	--local head = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD) or nil
	--local body = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY) or nil
	if hands ~= nil and hands.components.weapon and hands:HasTag("monsterwpn") then
		hands.components.weapon:SetDamage(35*2)
		inst:AddTag("runner")	
	end
end

local function UnEquip(inst)
	local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	if hands then
	--
	else
	inst:RemoveTag("runner")
	inst.sg:GoToState("matingcall")
	end 
end	

local function ApplyBuildOverrides(inst, animstate)
    local herd = inst.components.herdmember and inst.components.herdmember:GetHerd()
    local basebuild = (inst:HasTag("baby") and "beefalo_baby_build")
            or (inst.components.beard.bits == 0 and "beefalo_shaved_build")
            or (inst.components.domesticatable:IsDomesticated() and "beefalo_domesticated")
            or "beefalo_build"
    if animstate ~= nil and animstate ~= inst.AnimState then
        animstate:AddOverrideBuild(basebuild)
    else
        animstate:SetBuild(basebuild)
    end

    if (herd and herd.components.mood and herd.components.mood:IsInMood())
        or (inst.components.mood and inst.components.mood:IsInMood()) then
        animstate:Show("HEAT")
    else
        animstate:Hide("HEAT")
    end

    if tendencies[inst.tendency].build ~= nil then
        animstate:AddOverrideBuild(tendencies[inst.tendency].build)
    elseif animstate == inst.AnimState then
        -- this presumes that all the face builds have the same symbols
        animstate:ClearOverrideBuild("beefalo_personality_docile")
    end
end

local function CanShareTarget(dude)
    return dude:HasTag("beefalo")
        and not dude:IsInLimbo()
        and not (dude.components.health:IsDead() or dude:HasTag("player"))
end

local function OnAttacked(inst, data)
        inst.components.combat:SetTarget(data.attacker)
        inst.components.combat:ShareTarget(data.attacker, 30, CanShareTarget, 5)
 end

local function OnResetBeard(inst)
    inst.sg:GoToState("shaved")
end




local function CanShaveTest(inst)
    if inst.components.sleeper:IsAsleep() then
        return true
    else
        return false, "AWAKEBEEFALO"
    end
end

local NIGHTVISION_COLOURCUBES =
{
    day = "images/colour_cubes/insane_day_cc.tex",
    dusk = "images/colour_cubes/insane_dusk_cc.tex",
    night = "images/colour_cubes/purple_moon_cc.tex",
    full_moon = "images/colour_cubes/purple_moon_cc.tex",
}

local function SetNightVision(inst, enable)
    if TheWorld.state.isnight or TheWorld:HasTag("cave") then
        inst.components.playervision:ForceNightVision(true)
        inst.components.playervision:SetCustomCCTable(NIGHTVISION_COLOURCUBES)
    else
        inst.components.playervision:ForceNightVision(false)
        inst.components.playervision:SetCustomCCTable(nil)
    end
end

local function OnShaved(inst)
    inst.AnimState:SetBuild("beefalo_shaved_build")
end

local function OnHairGrowth(inst)
    if inst.components.beard.bits == 0 then
        inst.hairGrowthPending = true
        if inst.components.rideable ~= nil then
            inst.components.rideable:Buck()
        end
    end
end

local function RestoreNightvision(inst)

	inst:DoTaskInTime(3, function(inst) 
	inst.Light:Enable(true)
	inst.Light:SetRadius(0)
	inst.Light:SetFalloff(.1)
	inst.Light:SetIntensity(.1)
	inst.Light:SetColour(245/255,40/255,0/255)
	end, inst)
end
--------------------------------------------------
local function OnLoad(inst, data)
	if data ~= nil then
		inst.mobteleported = data.mobteleported or false
		inst.isshiny = data.isshiny or 0
	end
end

local function OnSave(inst, data)
	data.mobteleported = inst.mobteleported or false
	data.isshiny = inst.isshiny or 0
end

local function setSkin(inst)
	if not inst:HasTag("playerghost") then
		local mobskin = inst.components.skinner.skin_name
		local getshiny = (mobskin ~= inst.prefab and mobskin ~= "") and string.gsub(mobskin, inst.prefab.."_", "" ) --will return false if no skin is equipped.
		if SKIN_RARITY_COLORS.ModMade ~= nil then
			if getshiny ~= false then
				inst.isshiny = getshiny --used for other purposes
				inst.AnimState:SetBuild("beefalo_shiny_build_0"..inst.isshiny)
			end		
		end
	end	
end
------------------------------------------------------
----PvP Teleport----

local function getwildposition(inst)
    local ground = TheWorld
    local centers = {}
    for i, node in ipairs(ground.topology.nodes) do
        if ground.Map:IsPassableAtPoint(node.x, 0, node.y) then
            table.insert(centers, {x = node.x, z = node.y})
        end
    end
    if #centers > 0 then
        local pos = centers[math.random(#centers)]
        return Point(pos.x, 0, pos.z)
    else
        return inst:GetPosition()
    end
end

local function PvPTeleport(inst)
if inst.mobteleported == nil or inst.mobteleported == false then
	local ground = TheWorld
	local pt = getwildposition(inst)--Point(inst.Transform:GetWorldPosition())
      if pt.y <= .1 then
         pt.y = 0
         inst.Physics:Stop()
         inst.Physics:Teleport(pt.x,pt.y,pt.z)
		 inst.mobteleported = true
      end
	end
end

------------------------------------------------------

local function setChar(inst)
	if not inst:HasTag("playerghost") then
    inst.AnimState:SetBank("beefalo")
    inst.AnimState:SetBuild("beefalo_build")
    inst:SetStateGraph("SGbeefplayer")
	end
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	if MOBPVPMODE == "Enable" then
		PvPTeleport(inst)
	end
	inst.components.sanity.ignore = true
	inst.components.locomotor.walkspeed = TUNING.BEEFALO_WALK_SPEED
    inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED.DEFAULT
	inst.components.locomotor.fasteronroad = false
	
end

local function IsMonsterWeapon(item)
	return item.prefab == "monster_wpn"
end

local function OnDrop(inst)
    local monsterwpn = inst.components.inventory:FindItem(IsMonsterWeapon)
	local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	if monsterwpn == nil and not inst.components.inventory:IsFull() then
	--inst:DoTaskInTime(1, function (inst)
	 if hands ~= nil and hands:HasTag("monsterwpn") then
	 --
	 else
		
		inst:DoTaskInTime(1, function(inst) 
		inst.components.inventory:GiveItem(SpawnPrefab("monster_wpn"))
		end)
	end	
	--end)
	end
end

local function OnDropCheck(inst)
    
	inst:DoTaskInTime(1, function(inst)
	local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	if hands == nil or not hands:HasTag("monsterwpn") then
	OnDrop(inst)
	end
	end)
end

local function RemovePenalty(inst)
	inst.components.health:DeltaPenalty(-1.00) --Removes health penalty when reviving
	--inst.components.health:DoDelta(20000, false) --Returns health to max health upon reviving
end

local common_postinit = function(inst) 
	inst.soundsname = "beefalo"

	inst.MiniMapEntity:SetIcon( "beefplayer.tex" )

	inst:DoTaskInTime(0, function()
   if ThePlayer then
      inst:EnableMovementPrediction(false)
   end
end)

	inst:WatchWorldState( "isday", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "isdusk", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "isnight", function() SetNightVision(inst)  end)
	inst:WatchWorldState( "iscaveday", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "iscavedusk", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "iscavenight", function() SetNightVision(inst)  end)
	
	SetNightVision(inst)
end

local function SetMating(inst)
if TheWorld.state.isspring then
    inst.components.periodicspawner:SetRandomTimes(1800, 2000)
    inst.components.periodicspawner:SetDensityInRange(20, 2)
    inst.components.periodicspawner:SetMinimumSpacing(1)
	inst.AnimState:Show("HEAT")
	else
    inst.components.periodicspawner:SetRandomTimes(7200, 7500)
    inst.components.periodicspawner:SetDensityInRange(20, 2)
    inst.components.periodicspawner:SetMinimumSpacing(8)
	inst.AnimState:Hide("HEAT")
	end
end

local function DontTriggerCreep(inst)
    inst.components.locomotor.walkspeed = TUNING.BEEFALO_WALK_SPEED
    inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED.DEFAULT
end

local master_postinit = function(inst)
    inst.components.health:SetMaxHealth(700)
	inst.components.hunger:SetMax(250)
	--inst:AddComponent("healthRegenerate")
	inst.components.combat.playerdamagepercent = MOBPVP
    inst.components.combat:SetAttackPeriod(TUNING.HOUND_ATTACK_PERIOD)
	inst.components.combat:SetRange(TUNING.WORM_ATTACK_DIST)
    inst.components.locomotor.walkspeed = TUNING.BEEFALO_WALK_SPEED
    inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED.DEFAULT
	inst.components.combat:SetDefaultDamage(35*2)
	--inst.components.combat:SetHurtSound("dontstarve/creatures/hound/hit")
	--inst.components.temperature.hurtrate = 0
    inst.components.temperature.inherentinsulation = -TUNING.INSULATION_SMALL
	inst.AnimState:SetBank("beefalo")
	inst.AnimState:SetBuild("beefalo_build")	
	inst.OnSetSkin = function(skin_name)
    inst.AnimState:SetBuild("beefalo_build")
	inst:SetStateGraph("SGbeefplayer")
	
	inst:ListenForEvent("ms_respawnedfromghost", DontTriggerCreep)
    DontTriggerCreep(inst)
	
	
	end
	inst:SetStateGraph("SGbeefplayer")
	inst.components.locomotor:SetShouldRun(false)
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	inst.components.talker:IgnoreAll()
	inst.components.sanity.ignore = true
	
	inst:AddComponent("lootdropper")
    inst.components.lootdropper:SetChanceLootTable('beefplayer')
	
	inst.AnimState:Hide("HEAT")
	MakeLargeBurnableCharacter(inst, "beefalo_body")
	inst.components.temperature.maxtemp = 60
	inst.components.temperature.mintemp = 20
	
	inst:ListenForEvent("equip", Equip)
	inst:ListenForEvent("unequip", UnEquip)
	inst:ListenForEvent("itemlose", OnDropCheck)
	
	inst.sounds = sounds
	
	inst.taunt = true
	inst.specialatk2 = true
	inst.specialatk = true
	inst.beeffood = 0
	inst.beefkill = 0
	inst.beeflazy = 0
	inst.isshiny = 0
	inst.mobteleported = false
	
	inst:ListenForEvent("attacked", OnAttacked)
	inst:RemoveTag("character")
	inst:AddTag("beefalo")
	inst:AddTag("mobsleep")
	--inst:AddTag("runner")
	inst:AddTag("monster_user")
	inst:AddTag("mobplayer")
	--inst:AddTag("special_atk1")
    inst:AddTag("animal")
    --inst:AddTag("largecreature")
	
	 --local hair_growth_days = 3
	 
	--inst:AddComponent("beard")
	 -- assume the beefalo has already grown its hair
    --inst.components.beard.bits = 3
    --inst.components.beard.daysgrowth = hair_growth_days + 1
    --inst.components.beard.onreset = OnResetBeard
    --inst.components.beard.canshavetest = CanShaveTest
    --inst.components.beard.prize = "beefalowool"
    --inst.components.beard:AddCallback(0, OnShaved)
    --inst.components.beard:AddCallback(hair_growth_days, OnHairGrowth)
	
	inst.components.eater:SetDiet({ FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE }, { FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE })
    inst.components.eater:SetAbsorptionModifiers(4,1,1)

	MakeCharacterPhysics(inst, 10, .5)
    inst.DynamicShadow:SetSize(2.5, 1.5)
    inst.Transform:SetSixFaced()

	inst:AddComponent("periodicspawner")
    inst.components.periodicspawner:SetPrefab("babybeefalo")
    inst.components.periodicspawner:SetRandomTimes(480 * 12, 480 * 15)
    inst.components.periodicspawner:SetDensityInRange(20, 8)
    inst.components.periodicspawner:SetMinimumSpacing(1)
    --inst.components.periodicspawner:Start()
	
	--inst:WatchWorldState("isspring", SetMating)
	
	inst:AddComponent("shedder")
	inst.components.shedder.shedItemPrefab = "poop"
	inst.components.shedder.shedHeight = 0.1
	inst.components.shedder:StartShedding(180)
    
	
	
	------------------
    inst.ghostbuild = "ghost_monster_build"
    ------------------
	inst.OnSave = OnSave
    inst.OnLoad = OnLoad
	------------------
	
  	local light = inst.entity:AddLight()
  	inst.Light:Enable(true)
  	inst.Light:SetRadius(0)
  	inst.Light:SetFalloff(0.9)
  	inst.Light:SetIntensity(0.6)
  	inst.Light:SetColour(180/255,195/255,150/255)
	
	inst.components.talker.colour = Vector3(127/255, 0/255, 0/255)
	inst:ListenForEvent("respawnfromghost", RestoreNightvision)

    inst:DoTaskInTime(0, setChar)
	if SKIN_RARITY_COLORS.ModMade ~= nil then
	inst:DoTaskInTime(3, setSkin)
	end
    inst:ListenForEvent("respawnfromghost", function()
		inst:DoTaskInTime(3, function()  inst.components.health:SetInvincible(false)
            if inst.components.playercontroller ~= nil then
				inst.components.playercontroller:EnableMapControls(true)
				inst.components.playercontroller:Enable(true)
			end
			inst.components.inventory:Show()
			inst:ShowActions(true)
            inst:ShowHUD(true)
            inst:SetCameraDistance()
			inst.sg:RemoveStateTag("busy")
            SerializeUserSession(inst) 
		end)
        inst:DoTaskInTime(5, setChar)
		inst:DoTaskInTime(5.1, setSkin)
		inst:DoTaskInTime(6, RemovePenalty)
		inst:DoTaskInTime(10, RestoreNightvision)
    end)
	
    return inst
	
end

if SKIN_RARITY_COLORS.ModMade ~= nil then
AddModCharacterSkin("beefplayer", 1, {normal_skin = "deerclops_shiny_build_01", ghost_skin = "ghost_monster_build"}, {"deerclops_shiny_build_01", "ghost_monster_build"}, {"DEERPLAYER", "FORMAL"})
end

return MakePlayerCharacter("beefplayer", prefabs, assets, common_postinit, master_postinit, start_inv)
