local MakePlayerCharacter = require "prefabs/player_common"

--ToDo:
--Findout why Catcoon doesn't change speed. Like seriously.
local assets = 
{
	Asset("ANIM", "anim/catcoon_build.zip"),
	Asset("ANIM", "anim/catcoon_basic.zip"),
	Asset("ANIM", "anim/catcoon_actions.zip"),
	Asset("SOUND", "sound/catcoon.fsb"),
	--Asset("ANIM", "anim/ghost_waxwell_build.zip"),
	Asset("ANIM", "anim/catcoon_shiny_build_01.zip"),
	Asset("ANIM", "anim/catcoon_shiny_build_02.zip"),
}
local prefabs = {
	"mole",
	"rabbit",
	"flint",
	"tumbleweed",
	"cutgrass",
	"twigs",
	"berries",
	"goldnugget",
	"smallmeat",
	"silk",
	"coontail",
	"rocks",
	"bee",
	"mosquito",
	"cutreeds",
	"tentaclespots",
	"beefalowool",
	"feather_robin",
	"feather_robin_winter",
	"feather_crow",
	"boneshard",
	"red_cap",
	"blue_cap",
	"green_cap",
	"carrot_seeds",
	"corn_seeds",
	"pumpkin_seeds",
	"eggplant_seeds",
	"durian_seeds",
	"pomegranate_seeds",
	"dragonfruit_seeds",
	"watermelon_seeds",
	"butterfly",
	"robin",
	"robin_winter",
	"crow",
	"fish",
	"transistor",
	"froglegs",
	"batwing",
	"petals",
	"petals_evil",
	"ash",
	"acorn",
	"pinecone",
	"ice",
    }
local start_inv = {
	"coontail",
}

local start_inv2 = 
{
	"coontail",
	"cathome",
}

if MOBHOUSE == "Enable1" or MOBHOUSE == "Enable3" then
	start_inv = start_inv2
end

SetSharedLootTable( 'catplayer',
{
	{'meat',             1.00},
    {'coontail',		 0.33},
})

local neutralGiftPrefabs =
{
	{ --tier 1
		"wetgoop",
	},
	{ --tier 2
		"spoiled_food",
		"wetgoop",
	},
	{ --tier 3
		"cutgrass",
		"spoiled_food",
	},
	{ --tier 4
		"cutgrass",
		"spoiled_food",
	},
	{ --tier 5
		"cutgrass",
		"rocks",
		"petals_evil",
	},
	{ --tier 6
		"rocks",
		"flint",
		"petals",
	},
	{ --tier 7
		"ice",
		"flint",
		"pinecone",
	},
	{ --tier 8
		"flint",
		"pinecone",
		"feather_robin",
	},
	{ --tier 9
		"mole",
		"acorn",
	}
}

local friendGiftPrefabs =
{
	{ -- tier 1 (basic seeds)
		"carrot_seeds",
		"corn_seeds",
	},
	{ -- tier 2 (basic, generic stuff)
		"flint",
		"cutgrass",
		"twigs",
		"rocks",
		"ash",
		"pinecone",
		"petals",
		"petals_evil",
	},
	{ -- tier 3 (non-food animal bits)
		"feather_robin",
		"feather_robin_winter",
		"feather_crow",
		"boneshard",
	},
	{ -- tier 4 (better seeds)
		"pumpkin_seeds",
		"eggplant_seeds",
		"durian_seeds",
		"pomegranate_seeds",
		"dragonfruit_seeds",
		"watermelon_seeds",
	},
	{ --tier 5 (food)
		"ice",
		"batwing",
		"acorn",
		"berries",
		"smallmeat",
		"red_cap",
		"blue_cap",
		"green_cap",
		"fish",
		"froglegs",
	},
	{ --tier 6 (live animals + tumbleweed)
		"mole",
		"rabbit",
		"bee",
		"butterfly",
		"robin",
		"robin_winter",
		"crow",
		"tumbleweed",
	},
	{ -- tier 7 (good generic stuff)
		"goldnugget",
		"silk",
		"cutreeds",
		"tentaclespots",
		"beefalowool",
		"transistor",
	},
}

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 onupdate(inst, dt)
    inst.charge_time = inst.charge_time - dt
    if inst.charge_time <= 0 then
        inst.charge_time = 0
		if inst.charge_task ~= nil then
            inst.charge_task:Cancel()
            inst.charge_task = nil
        end
        inst.specialatk = true
		inst.sg:GoToState("ready")
    else
    --    
    end
end

local function OnLongUpdate(inst, dt)
    inst.charge_time = math.max(0, inst.charge_time - dt)
end

local function StartTimer(inst, duration)
    inst.charge_time = duration
	inst.specialatk = false

    if inst.charge_task == nil then
        inst.charge_task = inst:DoPeriodicTask(1, onupdate, nil, 1)
        onupdate(inst, 0)
    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 onload(inst, data)
    if data ~= nil and data.charge_time ~= nil then
        StartTimer(inst, data.charge_time)
    end
	if data ~= nil then
		inst.mobteleported = data.mobteleported or false
		inst.isshiny = data.isshiny or 0
	end	
end

local function onsave(inst, data)
    data.charge_time = inst.charge_time > 0 and inst.charge_time or nil
	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("catcoon_shiny_build_0"..inst.isshiny)
			end		
		end
	end	
end

local function setChar(inst)
	if not inst:HasTag("playerghost") then
    inst.AnimState:SetBank("catcoon")
    inst.AnimState:SetBuild("catcoon_build")
    inst:SetStateGraph("SGcatplayer")
	end
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	if MOBPVPMODE == "Enable" then
		PvPTeleport(inst)
	end
	inst.components.sanity.ignore = true
end

local function DontTriggerCreep(inst)
    inst.components.locomotor.runspeed = (11)
	inst.components.locomotor.fasteronroad = false
end

local NIGHTVISION_COLOURCUBES =
{
    day = "images/colour_cubes/mole_vision_off_cc.tex",
    dusk = "images/colour_cubes/mole_vision_on_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 PickRandomGift(inst, tier)
	local table = friendGiftPrefabs
	if tier > #table then tier = #table end
	return GetRandomItem(table[tier])
end

local function ShouldAcceptItem(inst, item)
	if item:HasTag("cattoy") or item:HasTag("catfood") or item:HasTag("cattoyairborne") then
		return true
	else
		return false
	end
end

local function OnGetItemFromPlayer(inst, item) 
        --giver:PushEvent("makefriend") --commenting this out because it could be used for something later.
        inst.last_hairball_time = GetTime()
        inst.hairball_friend_interval = math.random(2,4) -- Jumpstart the hairball timer (slot machine time!)
end

local function OnRefuseItem(inst, item) -- this might go unused
	inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/catcoon/hiss_pre")
	if inst.components.sleeper:IsAsleep() then
        inst.components.sleeper:WakeUp()
    -- elseif not inst.sg:HasStateTag("busy") then 
    -- 	inst.sg:GoToState("hiss")
    end
end

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

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

	inst.MiniMapEntity:SetIcon( "catplayer.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 CalcSanityAura(inst, observer)
	if inst.components.combat.target or MOBPVPMODE == "Enable" then
		return 0
	end

	return TUNING.SANITYAURA_MED
end


local master_postinit = function(inst)
    inst.components.health:SetMaxHealth(275)
	inst.components.hunger:SetMax(200)
	inst.components.hunger:SetRate(0.15)
	--inst:AddComponent("healthRegenerate")
    --inst.components.combat:SetAttackPeriod(TUNING.FIREHOUND_ATTACK_PERIOD)
	inst.components.combat.playerdamagepercent = MOBPVP
    inst.components.locomotor.runspeed = (15*3)
	inst.components.locomotor.walkspeed = (15*3)
	inst.components.locomotor.fasteronroad = false
	inst.components.combat:SetDefaultDamage(25*2)
	inst.components.combat:SetRange(TUNING.CATCOON_ATTACK_RANGE)
	inst.components.combat:SetHurtSound("dontstarve_DLC001/creatures/catcoon/hurt")
	--inst.components.temperature.hurtrate = 0
    inst.components.temperature.inherentinsulation = -TUNING.INSULATION_SMALL
	inst.AnimState:SetBank("catcoon")
	inst.AnimState:SetBuild("catcoon_build")	
	inst.OnSetSkin = function(skin_name)
    inst.AnimState:SetBuild("catcoon_build")
	inst:SetStateGraph("SGcatplayer")
	
	inst:ListenForEvent("ms_respawnedfromghost", DontTriggerCreep)
    DontTriggerCreep(inst)
	

	
	end
	inst:SetStateGraph("SGcatplayer")
	inst.components.locomotor:SetShouldRun(true)
	inst.components.talker:IgnoreAll()
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	inst.components.sanity.ignore = true
	
	inst:AddComponent("locomotor")
    --inst.components.locomotor:SetSlowMultiplier( 1 )
    --inst.components.locomotor:SetTriggersCreep(false)
    --inst.components.locomotor.pathcaps = { ignorecreep = true }
	--inst.components.locomotor:EnableGroundSpeedMultiplier(true)
	
	
	--inst.components.eater:SetDiet({ FOODTYPE.MEAT }, { FOODTYPE.MEAT })
    --inst.components.eater:SetCanEatHorrible()

    --inst.components.eater.strongstomach = true -- can eat monster meat!
	
	--inst.components.temperature.maxtemp = 60
	inst.components.temperature.mintemp = 20
	
	--inst:AddTag("smallcreature")
	--inst:AddTag("animal")
	inst:AddTag("catcoonp")
	inst:AddTag("mobsleep")
	inst:AddTag("mobplayer")
	inst:RemoveTag("character")
	
	inst.taunt = true
	inst.specialatk2 = true	
	inst.specialatk = true
	inst.mobteleported = false
	inst.isshiny = 0
	
	inst.ghostbuild = "ghost_monster_build"
	
	inst.userfunctions =
	{
		StartTimer = StartTimer,	
	}
	
	inst.charge_task = nil
    inst.charge_time = 0
	
	inst:AddComponent("sanityaura")

	inst.hairball_friend_interval = math.random(TUNING.MIN_HAIRBALL_FRIEND_INTERVAL, TUNING.MAX_HAIRBALL_FRIEND_INTERVAL)
    inst.hairball_neutral_interval = math.random(TUNING.MIN_HAIRBALL_NEUTRAL_INTERVAL, TUNING.MAX_HAIRBALL_NEUTRAL_INTERVAL)
	
	MakeCharacterPhysics(inst, 10, .5)
    inst.DynamicShadow:SetSize(1.5, 0.5)
    inst.Transform:SetFourFaced()

    inst.components.sanityaura.aurafn = CalcSanityAura
	
    inst:AddComponent("lootdropper")
	inst.components.lootdropper:SetChanceLootTable("catplayer")
    
	inst.neutralGiftPrefabs = neutralGiftPrefabs
	inst.friendGiftPrefabs = friendGiftPrefabs
	inst.PickRandomGift = PickRandomGift
	
	MakeSmallBurnableCharacter(inst, "catcoon_torso", Vector3(1,0,1))
	------------------
    inst.components.eater:SetAbsorptionModifiers(1,3,3)
    ------------------
	
	inst.OnLongUpdate = OnLongUpdate
	inst.OnSave = onsave
	inst.OnLoad = onload

	
  	local light = inst.entity:AddLight()
  	inst.Light:Enable(true)
  	inst.Light:SetRadius(0)
  	inst.Light:SetFalloff(0.1)
  	inst.Light:SetIntensity(0.1)
  	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)
		if SKIN_RARITY_COLORS.ModMade ~= nil then
		inst:DoTaskInTime(5.1, setSkin)
		end
		inst:DoTaskInTime(6, RemovePenalty)
		inst:DoTaskInTime(6, DontTriggerCreep)
		inst:DoTaskInTime(10, RestoreNightvision)
    end)
	
    return inst
	
end


if SKIN_RARITY_COLORS.ModMade ~= nil then
AddModCharacterSkin("catplayer", 1, {normal_skin = "catcoon_shiny_build_01", ghost_skin = "ghost_monster_build"}, {"catcoon_shiny_build_01", "ghost_monster_build"}, {"CATPLAYER", "FORMAL"})
AddModCharacterSkin("catplayer", 2, {normal_skin = "catcoon_shiny_build_02", ghost_skin = "ghost_monster_build"}, {"catcoon_shiny_build_02", "ghost_monster_build"}, {"CATPLAYER", "SHADOW"})
end

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