local MakePlayerCharacter = require "prefabs/player_common"

local assets = {

        Asset( "ANIM", "anim/player_basic.zip" ),
        Asset( "ANIM", "anim/player_idles_shiver.zip" ),
        Asset( "ANIM", "anim/player_actions.zip" ),
        Asset( "ANIM", "anim/player_actions_axe.zip" ),
        Asset( "ANIM", "anim/player_actions_pickaxe.zip" ),
        Asset( "ANIM", "anim/player_actions_shovel.zip" ),
        Asset( "ANIM", "anim/player_actions_blowdart.zip" ),
        Asset( "ANIM", "anim/player_actions_eat.zip" ),
        Asset( "ANIM", "anim/player_actions_item.zip" ),
        Asset( "ANIM", "anim/player_actions_uniqueitem.zip" ),
        Asset( "ANIM", "anim/player_actions_bugnet.zip" ),
        Asset( "ANIM", "anim/player_actions_fishing.zip" ),
        Asset( "ANIM", "anim/player_actions_boomerang.zip" ),
        Asset( "ANIM", "anim/player_bush_hat.zip" ),
        Asset( "ANIM", "anim/player_attacks.zip" ),
        Asset( "ANIM", "anim/player_idles.zip" ),
        Asset( "ANIM", "anim/player_rebirth.zip" ),
        Asset( "ANIM", "anim/player_jump.zip" ),
        Asset( "ANIM", "anim/player_amulet_resurrect.zip" ),
        Asset( "ANIM", "anim/player_teleport.zip" ),
        Asset( "ANIM", "anim/wilson_fx.zip" ),
        Asset( "ANIM", "anim/player_one_man_band.zip" ),
        Asset( "ANIM", "anim/shadow_hands.zip" ),
        Asset( "SOUND", "sound/sfx.fsb" ),
        Asset( "SOUND", "sound/wilson.fsb" ),
        Asset( "ANIM", "anim/beard.zip" ),

        Asset( "ANIM", "anim/caitlin.zip" ),
        Asset( "ANIM", "anim/paranoid_caitlin.zip" ),
        Asset( "ANIM", "anim/disorganized_caitlin.zip" ),
        Asset( "ANIM", "anim/psychotic_caitlin.zip" ),
}
local prefabs = {}
local start_inv = {
	"hat_paranoid",
	"hat_disorganized",
	"hat_psychotic",
}

local function applyscariness(inst)  --changes appearance based on amount of nightmare fuel eaten.
	
	--c1 = (1 - (inst.level * 0.125))
	--c2 = (1 - (inst.level * 0.0625))
	--scale = (0.95 + (inst.level * 0.05))
	
	if inst.level == 0 then
		inst.components.colourtweener:StartTween({1,1,1,1}, 0)
		inst.Transform:SetScale(.95,.95,.95)
		
	elseif inst.level == 1 then
		inst.components.colourtweener:StartTween({.875,.875,.875,.9375}, 0)
		inst.Transform:SetScale(1,1,1)
	
	elseif inst.level == 2 then
		inst.components.colourtweener:StartTween({.75,.75,.75,.875}, 0)
		inst.Transform:SetScale(1.05,1.05,1.05)
	
	elseif inst.level == 3 then
		inst.components.colourtweener:StartTween({.625,.625,.625,.8125}, 0)
		inst.Transform:SetScale(1.1,1.1,1.1)
	
	elseif inst.level == 4 then
		inst.components.colourtweener:StartTween({.5,.5,.5,.75}, 0)
		inst.Transform:SetScale(1.15,1.15,1.15)
	
	elseif inst.level == 5 then
		inst.components.colourtweener:StartTween({.375,.375,.375,.6875}, 0)
		inst.Transform:SetScale(1.2,1.2,1.2)
	
	elseif inst.level == 6 then
		inst.components.colourtweener:StartTween({.25,.25,.25,.625}, 0)
		inst.Transform:SetScale(1.25,1.25,1.25)
	
	elseif inst.level == 7 then
		inst.components.colourtweener:StartTween({.12,.12,.12,.5625}, 0)
		inst.Transform:SetScale(1.3,1.3,1.3)

	else
		inst.components.colourtweener:StartTween({0,0,0,.5}, 0)
		inst.Transform:SetScale(1.35,1.35,1.35)

	end
	
end

local function HallucinationSpawn(inst) --run sounds and animations, and spawn a Hallucination.
	
	inst.HUD:Hide()
	inst.sg:GoToState("death")
	inst.components.talker:Say("Urk...")
    inst:DoTaskInTime(2, function()
		inst.FriendSpawnChance = math.random()
			if inst.FriendSpawnChance < 0.5 then
				SpawnPrefab("schizo_friend").Transform:SetPosition(inst:GetPosition():Get())
			elseif inst.FriendSpawnChance > 0.75 then
				SpawnPrefab("terrorfriend").Transform:SetPosition(inst:GetPosition():Get())
			else
				SpawnPrefab("crawlingbuddy").Transform:SetPosition(inst:GetPosition():Get())
			end
		SpawnPrefab("statue_transition").Transform:SetPosition(inst:GetPosition():Get())
		inst.SoundEmitter:PlaySound("dontstarve/sanity/creature2/appear")
		inst.components.sanity:DoDelta(-25)
		inst.level = 0
		applyscariness(inst)
        inst:DoTaskInTime(1.2, function()
            inst.AnimState:PlayAnimation("amulet_rebirth")
            inst.SoundEmitter:PlaySound("dontstarve/common/rebirth_amulet_raise")
            inst.AnimState:OverrideSymbol("FX", "player_amulet_resurrect", "FX")
            TheCamera:SetDistance(14)
            inst:DoTaskInTime(2.5, function() 
                inst.SoundEmitter:PlaySound("dontstarve/common/rebirth_amulet_poof")
            end)
            inst:DoTaskInTime(3.5, function()
                inst.sg:GoToState("idle")
                inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_SCHIZOSPAWN"))
                inst.HUD:Show() 
            end)
        end)
    end)
end

local function oneat(inst, food)  --triggers appearence change and/or hallucinations on eating nightmare fuel
	
	if food and food.components.edible and food:HasTag("scaryfood") then
		--give an upgrade!
		inst.level = inst.level + 1
		applyscariness(inst)	
		inst.SoundEmitter:PlaySound("dontstarve/sanity/creature2/taunt")
		inst.HUD.controls.status.brain:PulseGreen()
		SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
		
		
		if inst.level == 8 then
			inst:DoTaskInTime(2, function()
				HallucinationSpawn(inst)
			end)
		end
	end
end

local orig_heal_fn = ACTIONS.HEAL.fn
local function disable_heal()  --disable healing
    ACTIONS.HEAL.fn = function(act) end
end
 
local function enable_heal()  --enable healing
    ACTIONS.HEAL.fn = orig_heal_fn
end

local function onkill(inst, data)  --recover health and hunger when killing in paranoid form
	if inst:HasTag("paranoid") then 
		if data.cause == inst.prefab and not data.inst:HasTag("prey") and not data.inst:HasTag("veggie") and not data.inst:HasTag("structure") then
			local delta = (data.inst.components.health.maxhealth * 0.025 )
			inst.components.health:DoDelta(delta * 2, false, "psychopathy")
			inst.components.hunger:DoDelta(delta, false, "psychopathy")
			inst.SoundEmitter:PlaySound("dontstarve/sanity/creature2/death")
			inst.BondQuipChance = math.random()
			if inst.BondQuipChance < 0.25 or delta > 31 then --25% quip chance on all creatures, 100% quip chance on boss mobs.
				inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_PSYCHOPATHY"))
			end
		end
	end
end

local function DefaultStats(inst) --normal mode stats
	
	inst.AnimState:SetBuild("caitlin")

	inst:RemoveTag("paranoid")
	inst:RemoveTag("psychotic")
	inst:RemoveTag("disorganized")
	inst:RemoveTag("insomniac")
	
	STRINGS.CHARACTERS.CAITLIN = require "speech_caitlin"
	inst.components.talker.special_speech = false
	
    local percent = inst.components.health:GetPercent()
	inst.components.health:SetMaxHealth(110)
    inst.components.health:SetPercent(percent)
	inst.components.health:StopRegen()
	if IsDLCEnabled(REIGN_OF_GIANTS) then
		inst.components.health:SetAbsorptionAmount(0)
	else
		inst.components.health:SetAbsorbAmount(0)
	end
	enable_heal()
	
    local hunger_percent = inst.components.hunger:GetPercent()
	inst.components.hunger:SetMax(110)
    inst.components.hunger:SetPercent(hunger_percent)
	inst.components.hunger:SetKillRate(1)

    local sanity_percent = inst.components.sanity:GetPercent()
	inst.components.sanity:SetMax(100)
    inst.components.sanity:SetPercent(sanity_percent)
	inst.components.sanity.neg_aura_mult = 1.5
	inst.components.sanity.night_drain_mult = 1.5

	inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 1.2)
	inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 1.2)
	inst.components.combat.damagemultiplier = 1
	inst.components.combat:SetAttackPeriod(0.5)
	inst.components.eater:SetOmnivore()
	inst.Light:Enable(false)
end

local function ParanoidStats(inst) --attack form stats
	
	inst.AnimState:SetBuild("paranoid_caitlin")

	inst:RemoveTag("psychotic")
	inst:RemoveTag("disorganized")
	inst:AddTag("paranoid")
	inst:AddTag("insomniac")
	
	STRINGS.CHARACTERS.CAITLIN = require "speech_caitlinatk"
	inst.components.talker.special_speech = false
	
    local percent = inst.components.health:GetPercent()
	inst.components.health:SetMaxHealth(150)
    inst.components.health:SetPercent(percent)
	inst.components.health:StopRegen()
	if IsDLCEnabled(REIGN_OF_GIANTS) then
		inst.components.health:SetAbsorptionAmount(0)
	else
		inst.components.health:SetAbsorbAmount(0)
	end
	disable_heal()
	
    local hunger_percent = inst.components.hunger:GetPercent()
	inst.components.hunger:SetMax(50)
    inst.components.hunger:SetPercent(hunger_percent)
	inst.components.hunger:SetKillRate(0.75)

    local sanity_percent = inst.components.sanity:GetPercent()
	inst.components.sanity:SetMax(150)
    inst.components.sanity:SetPercent(sanity_percent)
	inst.components.sanity.neg_aura_mult = 2
	inst.components.sanity.night_drain_mult = 1

	inst.components.locomotor.walkspeed = TUNING.WILSON_WALK_SPEED
	inst.components.locomotor.runspeed = TUNING.WILSON_RUN_SPEED
	inst.components.combat.damagemultiplier = 4
	inst.components.combat:SetAttackPeriod(1)
	inst.components.eater.foodprefs = { "HORRIBLE" }
	inst.Light:Enable(false)
	
    inst:ListenForEvent("entity_death", function(wrld, data) onkill(inst, data) end, GetWorld())

end

local function DisorganizedStats(inst) --speed form stats

	inst.AnimState:SetBuild("disorganized_caitlin")

	inst:RemoveTag("paranoid")
	inst:RemoveTag("psychotic")
	inst:RemoveTag("insomniac")
	inst:AddTag("disorganized")
	
	STRINGS.CHARACTERS.CAITLIN = require "speech_caitlinspd"
	inst.components.talker.special_speech = false
	
    local percent = inst.components.health:GetPercent()
	inst.components.health:SetMaxHealth(50)
    inst.components.health:SetPercent(percent)
	inst.components.health:StopRegen()
	if IsDLCEnabled(REIGN_OF_GIANTS) then
		inst.components.health:SetAbsorptionAmount(0)
	else
		inst.components.health:SetAbsorbAmount(0)
	end
	enable_heal()
	
    local hunger_percent = inst.components.hunger:GetPercent()
	inst.components.hunger:SetMax(150)
    inst.components.hunger:SetPercent(hunger_percent)
	inst.components.hunger:SetKillRate(1)

    local sanity_percent = inst.components.sanity:GetPercent()
	inst.components.sanity:SetMax(150)
    inst.components.sanity:SetPercent(sanity_percent)
	inst.components.sanity.neg_aura_mult = 1
	inst.components.sanity.night_drain_mult = 2

	inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 3)
	inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 3)
	inst.components.combat.damagemultiplier = 1
	inst.components.combat:SetAttackPeriod(0.5)
	inst.components.eater:SetOmnivore()
	inst.Light:Enable(true)
end

local function PsychoticStats(inst) --defense form stats

	inst.AnimState:SetBuild("psychotic_caitlin")

	inst:RemoveTag("paranoid")
	inst:RemoveTag("disorganized")
	inst:RemoveTag("insomniac")
	inst:AddTag("psychotic")
	
	inst.components.talker.special_speech = true
	
    local percent = inst.components.health:GetPercent()
	inst.components.health:SetMaxHealth(250)
    inst.components.health:SetPercent(percent)
	inst.components.health:StartRegen(2.5, 1)
	if IsDLCEnabled(REIGN_OF_GIANTS) then
		inst.components.health:SetAbsorptionAmount(0.5)
	else
		inst.components.health:SetAbsorbAmount(0.5)
	end
	enable_heal()
	
    local hunger_percent = inst.components.hunger:GetPercent()
	inst.components.hunger:SetMax(150)
    inst.components.hunger:SetPercent(hunger_percent)
	inst.components.hunger:SetKillRate(10)

    local sanity_percent = inst.components.sanity:GetPercent()
	inst.components.sanity:SetMax(50)
    inst.components.sanity:SetPercent(sanity_percent)
	inst.components.sanity.neg_aura_mult = 1.25
	inst.components.sanity.night_drain_mult = 1.25

	inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 0.66)
	inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 0.66)
	inst.components.combat.damagemultiplier = 0.67
	inst.components.combat:SetAttackPeriod(0.5)
	inst.components.eater:SetOmnivore()
	inst.Light:Enable(false)
	
end

local function TurnSchizo(inst) --play animations and apply stats.

	if not inst.components.health:IsDead() then
		inst:DoTaskInTime(1, function()
			SpawnPrefab("statue_transition").Transform:SetPosition(inst:GetPosition():Get())
			SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get()) 
			inst.sg:GoToState("teleportato_teleport")
			inst.SoundEmitter:PlaySound("dontstarve/charlie/warn")
			inst:DoTaskInTime(3, function()
				SpawnPrefab("statue_transition").Transform:SetPosition(inst:GetPosition():Get())
				inst.SoundEmitter:PlaySound("dontstarve/creatures/deerclops/death")
				if inst:HasTag("trigger_paranoia") then	
					ParanoidStats(inst)
				elseif inst:HasTag("trigger_psychosis") then
					PsychoticStats(inst)
				elseif inst:HasTag("trigger_disorganized") then

					DisorganizedStats(inst)
				else
					DefaultStats(inst)
				end
				inst:DoTaskInTime(3, function()
					inst.sg:GoToState("wakeup")
					inst.SoundEmitter:PlaySound("dontstarve/common/rebirth_amulet_poof")
					inst.AnimState:OverrideSymbol("FX", "player_amulet_resurrect", "FX")
					TheCamera:SetDistance(14)
					SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get()) 

					inst.SchizoSpawnChance = math.random()			--Spawn hallucination
						if inst.SchizoSpawnChance < 0.05 then
							SpawnPrefab("schizo_friend").Transform:SetPosition(inst:GetPosition():Get())
							SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
							inst.components.sanity:DoDelta(-10)
						elseif inst.SchizoSpawnChance < 0.075 then
							SpawnPrefab("terrorfriend").Transform:SetPosition(inst:GetPosition():Get())
							SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
							inst.components.sanity:DoDelta(-10)
						elseif inst.SchizoSpawnChance < 0.1 then
							SpawnPrefab("crawlingbuddy").Transform:SetPosition(inst:GetPosition():Get())
							SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
							inst.components.sanity:DoDelta(-10)
						end
					
					if not inst:HasTag("paranoid") then				--hunger penalty
						inst.components.hunger:DoDelta(-30, false, "transformation")
					else
						inst.components.hunger:DoDelta(-20, false, "transformation")
					end
					
					if not inst:HasTag("psychotic") then			--sanity penalty
						inst.components.sanity:DoDelta(-15)
					else
						inst.components.sanity:DoDelta(-10)
					end
					
					if inst.level > 0 then
						inst.level = inst.level - 1
						applyscariness(inst)
					end
					inst:DoTaskInTime(3.5, function()
						if inst:HasTag("paranoid") then
							inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_PARANOID"))
						elseif inst:HasTag("disorganized") then
							inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_DISORGANIZED"))
						elseif inst:HasTag("psychotic") then
							inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_PSYCHOTIC"))
						else
							inst.components.talker:Say(GetString("caitlin", "ANNOUNCE_NORMALFORM"))
						end
						inst.sg:GoToState("idle")
						if inst:HasTag("trigger_disorganized") then
							inst.HUD.controls.mapcontrols.minimapBtn:Hide()
							inst.HUD.controls.crafttabs:Hide()
						else
							inst.HUD.controls.mapcontrols.minimapBtn:Show()
							inst.HUD.controls.crafttabs:Show()
						end
						inst.components.health:DoDelta(1, false, "transformation")
					end)
				end)
			end)
		end)
	end	
end

local function OnSave(inst, data) --save this data to savefile
	data.RetainHealth = inst.components.health.currenthealth --we need this because the health functions are dumb :P
	data.level = inst.level
end

local function OnLoad(inst, data) --load this data from savefile on new session start		
		if data.level then
			inst.level = data.level
			applyscariness(inst)
		end
		inst.components.health:SetVal(inst.components.health.currenthealth)
		inst.components.health:DoDelta(0, true)
	end

local fn = function(inst)

	inst.level = 0
	
	STRINGS.CHARACTERS.CAITLIN = require "speech_caitlin"
	
	inst.soundsname = "wallace"
	inst.MiniMapEntity:SetIcon( "caitlin.tex" )
	
	-- Starting Stats	
	inst.components.health:SetMaxHealth(110)
	inst.components.hunger:SetMax(110)
	inst.components.sanity:SetMax(110)
	inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 1.2)
	inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 1.2)
	inst.components.sanity.night_drain_mult = 1.5
	inst.components.sanity.neg_aura_mult = 1.5
	inst.components.inventory:GuaranteeItems(start_inv)
	
	inst:AddComponent("colourtweener")	
	inst.components.eater:SetOnEatFn(oneat)
	applyscariness(inst)
	
	inst:ListenForEvent("formchange", TurnSchizo)
	
	inst.components.sanitymonsterspawner:UpdateMonsters(20)
    inst.components.sanitymonsterspawner:UpdateMonsters(20)
	
	inst.entity:AddLight()
    inst.Light:Enable(false)
	inst.Light:SetRadius(3)
    inst.Light:SetFalloff(.5)
    inst.Light:SetIntensity(.6)
	
	inst.OnSave=OnSave 
    inst.OnLoad=OnLoad
end

return MakePlayerCharacter("caitlin", prefabs, assets, fn, start_inv)
