require "prefabutil"
local brain = require "brains/qiuqiu_brain"
require "stategraphs/SGqiuqiu"

local assets=
{
    Asset("ANIM", "anim/qiuqiu.zip"),
}

local prefabs =
{
	"lightbulb",
    "chester_eyebone",
    "die_fx",
    "chesterlight",
    "sparklefx",
}

local function OnOpen(inst)
    if not inst.components.health:IsDead() then
        inst.sg:GoToState("open")
    end
end 

local function OnClose(inst) 
    if not inst.components.health:IsDead() then
        inst.sg:GoToState("idle")
    end
end

local slotpos_3x1 = {}
for y = 0, 0 do
	for x = 0, 2 do
	table.insert(slotpos_3x1, Vector3(80*x-80*2+80, 80*y-80*2+80,0))
	end
end

local slotpos_3x2 = {}
for y = 0, 1 do
    for x = 0, 2 do
	table.insert(slotpos_3x2, Vector3(80*x-80*2+80, 80*y-80*2+80,0))
	end
end

local slotpos_3x3 = {}
for y = 2, 0, -1 do
    for x = 0, 2 do
        table.insert(slotpos_3x3, Vector3(80*x-80*2+80, 80*y-80*2+80,0))
    end
end

local function OnStopFollowing(inst) 
    inst:RemoveTag("companion")
end

local function OnStartFollowing(inst) 
    inst:AddTag("companion")
end

local function qiuqiu_up1(inst, dofx)
    inst.components.container:SetNumSlots(#slotpos_3x2)
    inst.components.container.widgetslotpos = slotpos_3x2
    inst.components.container.widgetanimbank = "ui_chest_3x3"
    inst.components.container.widgetanimbuild = "ui_chest_3x3"
    inst.components.container.widgetpos = Vector3(0,200,0)
    inst.components.container.side_align_tip = 160
    inst.components.container.canbeopened = true
end

local function qiuqiu_up2(inst, dofx)
    inst.components.container:SetNumSlots(#slotpos_3x3)
    inst.components.container.widgetslotpos = slotpos_3x3
    inst.components.container.widgetanimbank = "ui_chest_3x3"
    inst.components.container.widgetanimbuild = "ui_chest_3x3"
    inst.components.container.widgetpos = Vector3(0,200,0)
    inst.components.container.side_align_tip = 160
    inst.components.container.canbeopened = true
end


local function TakeItem1(yiyusword)
	if not yiyusword:HasTag("broken") and yiyusword.components.weapon and yiyusword.weaponexp and yiyusword.weapon_adddmg then
    yiyusword.components.weapon:SetDamage(45+yiyusword.weaponexp/150+yiyusword.weapon_adddmg)
    yiyusword.components.equippable.runspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyusword.weaponexp / 10000
    yiyusword.components.equippable.walkspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyusword.weaponexp / 10000
	elseif yiyusword:HasTag("broken") then
    yiyusword.components.weapon:SetDamage(45+yiyusword.weaponexp/150+yiyusword.weapon_adddmg)
    yiyusword.components.equippable.runspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyusword.weaponexp / 10000
    yiyusword.components.equippable.walkspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyusword.weaponexp / 10000
	yiyusword:RemoveTag("broken")
	end
end

local function TakeItem2(guangmang)
	if not guangmang:HasTag("broken") and guangmang.components.weapon and guangmang.weaponexp and guangmang.weapon_adddmg then
    guangmang.components.weapon:SetDamage(35+guangmang.weaponexp/150+guangmang.weapon_adddmg)
    guangmang.components.equippable.runspeedmult = TUNING.CANE_SPEED_MULT - 0.05 + guangmang.weaponexp / 10000
    guangmang.components.equippable.walkspeedmult = TUNING.CANE_SPEED_MULT - 0.05 + guangmang.weaponexp / 10000
	elseif guangmang:HasTag("broken") then
    guangmang.components.weapon:SetDamage(35+guangmang.weaponexp/150+guangmang.weapon_adddmg)
    guangmang.components.equippable.runspeedmult = TUNING.CANE_SPEED_MULT - 0.05 + guangmang.weaponexp / 10000
    guangmang.components.equippable.walkspeedmult = TUNING.CANE_SPEED_MULT - 0.05 + guangmang.weaponexp / 10000
	guangmang:RemoveTag("broken")
	end
end

local function TakeItem3(leiting)
	if not leiting:HasTag("broken") and leiting.components.weapon and leiting.weaponexp and leiting.weapon_adddmg then
    leiting.components.weapon:SetDamage(55+leiting.weaponexp/150+leiting.weapon_adddmg)
	elseif leiting:HasTag("broken") then
    leiting.components.weapon:SetDamage(55+leiting.weaponexp/150+leiting.weapon_adddmg)
	leiting:RemoveTag("broken")
	end
end

local function TakeItem4(yiyuhuan)
	if yiyuhuan.components.weapon and yiyuhuan.weaponexp and yiyuhuan.weapon_adddmg then
    yiyuhuan.components.weapon:SetDamage(15 + yiyuhuan.weaponexp/5 +yiyuhuan.weapon_adddmg)
    yiyuhuan.components.equippable.runspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyuhuan.weaponexp / 3000
    yiyuhuan.components.equippable.walkspeedmult = TUNING.CANE_SPEED_MULT - 0.1 + yiyuhuan.weaponexp / 3000
	end
	if yiyuhuan:HasTag("broken") then yiyuhuan:RemoveTag("broken") end
end

local widgetbuttoninfo = {
    text = TUNING.XIUFU,
    position = Vector3(0, -165, 0),
    fn = function(inst)
	if inst.components.container:Has("zijing", 3) and inst.qiuqiu_level and inst.qiuqiu_level == 1 then
		inst.qiuqiu_level = 2
		inst.components.container:ConsumeByName("zijing", 3)
        GetPlayer().SoundEmitter:PlaySound("dontstarve/HUD/research_available")
        inst.components.container:Close(GetPlayer())
		inst.sg:GoToState("cook")
        qiuqiu_up1(inst)
	elseif inst.components.container:Has("zijing", 6) and inst.qiuqiu_level and inst.qiuqiu_level == 2 then
		inst.qiuqiu_level = 3
		inst.components.container:ConsumeByName("zijing", 6)
        GetPlayer().SoundEmitter:PlaySound("dontstarve/HUD/research_available")
        inst.components.container:Close(GetPlayer())
		inst.sg:GoToState("cook")
        qiuqiu_up2(inst)
	elseif inst.components.container:Has("yiyucrystal", 5) then
        GetPlayer().SoundEmitter:PlaySound("dontstarve/HUD/research_available")
        inst.components.container:Close(GetPlayer())
		inst.components.container:ConsumeByName("yiyucrystal", 5)
		inst.sg:GoToState("cook")
        for k,v in pairs(inst.components.container.slots) do
            if v.components.fueled then
               v.components.fueled.currentfuel = v.components.fueled.maxfuel
            end
			if v.prefab ~= "yiyusword" then
			TakeItem1(v)
			end
			if v.prefab ~= "guangmang" then
			TakeItem2(v)
			end
			if v.prefab ~= "leiting" then
			TakeItem3(v)
			end
			if v.prefab ~= "yiyuhuan" then
			TakeItem4(v)
			end
            if v.components.finiteuses and v.prefab ~= "writingbrush" and v.prefab ~= "gardenershovel" and v.prefab ~= "bell" and v.prefab ~= "magicflute"
			and v.prefab ~= "greenstaff" and v.prefab ~= "greenamulet" and v.prefab ~= "featherfan" and v.prefab ~= "staff_tornado" and v.prefab ~= "book_gardening"
			and v.prefab ~= "tropicalfan" and v.prefab ~= "telescope" and v.prefab ~= "supertelescope" and v.prefab ~= "boatcannon" then

               v.components.finiteuses.current = v.components.finiteuses.total
            end
            if v.components.armor then
               v.components.armor.condition = v.components.armor.maxcondition
            end
            if v.components.perishable then
               v.components.perishable.perishremainingtime = v.components.perishable.perishtime
            end
            if v.components.moisturelistener then
               v.components.moisturelistener.wet = false
            end
        end
	elseif inst.qiuqiu_level == 1 then
		inst.components.talker:Say(TUNING.TALK10)
	elseif inst.qiuqiu_level == 2 then
		inst.components.talker:Say(TUNING.TALK17)
	end
end}

local function OnPooped(inst, spawn)
 inst.sg:GoToState("command")
 SpawnPrefab("sparklefx").Transform:SetPosition(inst:GetPosition():Get())
 SpawnPrefab("sparks").Transform:SetPosition(inst:GetPosition():Get())
end

local function OnAttacked(inst, data)
local attacker =data.attacker
if not attacker.components.yiyucast then
    inst.components.combat:SetTarget(data.attacker)
end
end

local function Retargetfn(inst)
	local notags = {"FX", "NOCLICK","INLIMBO", "monster"}
	if inst:HasTag("mode3") then
	return FindEntity(GetPlayer(), 30, function(guy) return guy.components.combat and inst.components.combat:CanTarget(guy) and not guy.prefab == "slurper" and not guy.components.yiyucast and guy:HasTag("monster") end)
	elseif inst:HasTag("mode2") then
	return FindEntity(GetPlayer(), 15,
        function(guy) return not guy.prefab == "slurper" and not guy:HasTag("wall") and not guy:HasTag("chester") and
		not guy.components.yiyucast and guy.components.health and not guy.components.health:IsDead() and inst.components.combat:CanTarget(guy)
		and (guy.components.combat.target == GetPlayer() or GetPlayer().components.combat.target == guy or guy.components.combat.target == inst or inst.components.combat.target == guy or guy:HasTag("monster"))
    end, nil, notags)
	elseif inst:HasTag("mode1") then
	return nil
	end
end

local function keeptargetfn(inst, target)
	if inst:HasTag("mode3") then
    if target.components.health and target.components.health.invincible then return false end
	print("sss")
    return target and target:IsValid()
	else
	return target and target:IsValid() and not target.components.yiyucast and not target:HasTag("wall")
		and target.components.combat and inst.components.combat:CanTarget(target) and not target:HasTag("chester") and not inst:HasTag("mode1")
        and target.components.health and not target.components.health:IsDead() and not target:HasTag("chester") and not target:HasTag("myfriend")
end
end

local function Specialattack(inst, data)
	local target = data.target
	local chance = math.random()
	if target and target.components.freezable and target.prefab ~= "yiyu_deerclops" and chance <= 0.10 then
		target.components.freezable:AddColdness(1)
	elseif target and target.components.burnable and chance <= 0.20 and target.prefab ~= "yiyu_deerclops" then
		target.components.burnable:Ignite()
	elseif target and chance <= 0.30 then
		if target.components.locomotor then target.components.locomotor:Stop() end
		inst.SoundEmitter:PlaySound("dontstarve/common/lightningrod")
		SpawnPrefab("lightning_rod_fx").Transform:SetPosition(target.Transform:GetWorldPosition())
	end
	if target and target.components.burnable and target.components.burnable:IsBurning() then
        target.components.burnable:Extinguish()
	end
end

local function OnPreLoad(inst, data)
    if not data then return end
	if data and data.qiuqiu_exp then
		inst.qiuqiu_exp = data.qiuqiu_exp
		inst.qiuqiu_level = data.qiuqiu_level
	end
    if data.qiuqiu_level == 2 then
        qiuqiu_up1(inst)
	elseif data.qiuqiu_level == 3 then
        qiuqiu_up2(inst)
    end
end

local function onload(inst, data)
    if not data then return end
	if data and data.qiuqiu_exp then
		inst.qiuqiu_exp = data.qiuqiu_exp
		inst.qiuqiu_level = data.qiuqiu_level
	end
    if data.qiuqiu_level == 2 then
        qiuqiu_up1(inst)
	elseif data.qiuqiu_level == 3 then
        qiuqiu_up2(inst)
    end
end

local function onsave(inst, data)
	data.qiuqiu_exp = inst.qiuqiu_exp
	data.qiuqiu_level = inst.qiuqiu_level
end

local function ondeath(inst, deadthing)
    if inst and deadthing and deadthing.components.yiyucast then
    local apple = TheSim:FindFirstEntityWithTag("yiyu_apple")
	if inst.components.follower.leader ~= apple then
		inst.components.follower:SetLeader(apple)
		inst.components.combat:SetTarget(nil)
	end
	end
end

local function taskleader(inst)
	local apples = GetPlayer().components.inventory:FindItem(function(item) return (item.prefab == "yiyu_apple") end)
    local apple = TheSim:FindFirstEntityWithTag("yiyu_apple")
	local pos = Vector3(inst.Transform:GetWorldPosition())
	local ents = TheSim:FindEntities(pos.x,pos.y,pos.z, 30)

		for k,v in pairs(ents) do
		if inst:HasTag("mode3") then
			if v and v.components.combat and v.prefab ~= "slurper" and not v:HasTag("wall") and not v:HasTag("chester") 
			and not v.components.yiyucast and (v.components.combat.target == GetPlayer() or v:HasTag("monster")) then
--				v.components.combat:SetTarget(GetPlayer() or nil)
				inst.components.combat:SuggestTarget(v)
			end
		elseif inst:HasTag("mode1") then
			if v and v.components.combat and v.components.combat.target == inst then
				v.components.combat:SetTarget(GetPlayer() or nil)
			end
		end
	end

	if not TheSim:FindFirstEntityWithTag("yiyu_apple") then inst:Remove() end
	if TheSim:FindFirstEntityWithTag("yiyu_apple") then
	if inst.components.follower.leader ~= apple and not apples then
		inst.components.follower:SetLeader(apple)
		inst.components.combat:SetTarget(nil)
		print("leader change")
	elseif inst.components.follower.leader ~= GetPlayer() and apples then
		inst.components.follower:SetLeader(GetPlayer())
	end
	end
end

local function init_prefab()
    local inst = CreateEntity()
    local trans = inst.entity:AddTransform()
    local anim = inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.Transform:SetFourFaced()

	if IsDLCEnabled(CAPY_DLC) then
		MakeAmphibiousCharacterPhysics(inst, 10, .5)
	else
		MakeCharacterPhysics(inst, 10, .5)
		inst.Physics:SetCollisionGroup(COLLISION.CHARACTERS)
		inst.Physics:ClearCollisionMask()
		inst.Physics:CollidesWith(COLLISION.WORLD)
		inst.Physics:CollidesWith(COLLISION.OBSTACLES)
		inst.Physics:CollidesWith(COLLISION.CHARACTERS)
	end

	inst:AddComponent("named")
	inst.components.named:SetName(STRINGS.NAMES.QIUQIU)

    anim:SetBank("qiuqiu")
    anim:SetBuild("qiuqiu")

	inst:AddTag("mode1")
    inst:AddTag("nosteal")
    inst:AddTag("scarytoprey")
    inst:AddTag("notraptrigger")
    inst:AddTag("cattoy")
	inst:AddTag("myfriend")
    inst:AddTag("noauradamage")
	inst:AddTag("amphibious")
	inst:AddTag("qiuqiu")
--	inst:AddTag("shadow")

    inst:AddComponent("locomotor")
    inst.components.locomotor.walkspeed = 8
    inst.components.locomotor.runspeed = 10

    inst:AddComponent("talker")
    inst.components.talker.fontsize = 24
	inst.components.talker.offset = Vector3(0,-800,0)
    inst.components.talker.colour = Vector3(0.75, 0.85, 1, 1)

	inst:AddComponent("health")
	inst.components.health:SetMaxHealth(100)
	inst.components.health.fire_damage_scale = 0
	inst.components.health.canmurder = false
	inst.components.health:SetInvincible(true)

    inst:AddComponent("container")
    inst.components.container.onopenfn = OnOpen
    inst.components.container.onclosefn = OnClose
    inst.components.container:SetNumSlots(#slotpos_3x1)
    inst.components.container.widgetslotpos = slotpos_3x1
    inst.components.container.widgetanimbank = "ui_chest_3x3"
    inst.components.container.widgetanimbuild = "ui_chest_3x3"
    inst.components.container.widgetpos = Vector3(0,200,0)
    inst.components.container.side_align_tip = 160
    inst.components.container.widgetbuttoninfo = widgetbuttoninfo
    inst.components.container.canbeopened = true

	inst:AddComponent("characterspecific")
    inst.components.characterspecific:SetOwner("yiyu")
    inst:AddComponent("knownlocations")

	inst:AddComponent("follower")
    inst:ListenForEvent("stopfollowing", OnStopFollowing)
    inst:ListenForEvent("startfollowing", OnStartFollowing)

	inst.entity:AddLight()
	inst.Light:SetFalloff(.5)
	inst.Light:SetIntensity(.5)
	inst.Light:SetRadius(.75)
	inst.Light:SetColour(180/255, 195/255, 50/255)
	inst.Light:Enable(false)  

    inst:AddComponent("combat")
	inst.components.combat:SetRange(3)
	inst.components.combat:SetDefaultDamage(TUNING.QQ_DAMAGE)
	inst.components.combat:SetAttackPeriod(1.5)
	inst.components.combat:SetRetargetFunction(1, Retargetfn)
	inst.components.combat:SetKeepTargetFunction(keeptargetfn)

	inst.OnSave = onsave
	inst.OnLoad = onload
	inst.OnPreLoad = OnPreLoad

	inst.qiuqiu_exp = 0
	inst.qiuqiu_level = 1
	inst:SetStateGraph("SGqiuqiu")
	local brain = require "brains/qiuqiu_brain"
	inst:SetBrain(brain)
	inst:ListenForEvent("onhitother", Specialattack)
    inst:ListenForEvent("attacked", OnAttacked)
	inst:ListenForEvent( "daytime", function() inst.Light:Enable(false) end , GetWorld() )
	inst:ListenForEvent( "dusktime", function() inst.Light:Enable(true) end , GetWorld() )
    inst:ListenForEvent("entity_death", function(world, data) ondeath(inst, data.inst) end, GetWorld())

	TheInput:AddKeyUpHandler(TUNING.YIYU_KEY9, function()
	local x,y,z = GetPlayer().Transform:GetWorldPosition()
	inst.components.talker.fontsize = 26
	inst.components.talker.colour = Vector3(0.7, 0.7, 0.7, 1)
	if inst.components.follower.leader == GetPlayer() then
	if inst:HasTag("mode1") then
		if inst.taskqiuqiu then inst.taskqiuqiu:Cancel() inst.taskqiuqiu=nil end
        inst:AddTag("mode2")
		inst:RemoveTag("mode1")
		GetPlayer().components.talker:Say(TUNING.TALK9)
	elseif inst:HasTag("mode2") then
        inst:AddTag("mode3")
		inst:RemoveTag("mode2")
		GetPlayer().components.talker:Say(TUNING.TALK18)
	elseif inst:HasTag("mode3") then
		if inst.taskqiuqiu then inst.taskqiuqiu:Cancel() inst.taskqiuqiu=nil end
        inst:AddTag("mode1")
		inst:RemoveTag("mode3")
		inst.components.combat:SetTarget(nil)
		GetPlayer().components.talker:Say(TUNING.TALK8)
	end
	end
	end)

	inst.taskleader = inst:DoPeriodicTask(1, function() taskleader(inst) end)

    return inst
end

return Prefab( "monsters/qiuqiu", init_prefab, assets, nil)
