require "prefabutil"
local tent_assets = { Asset("ANIM", "anim/tent.zip"), }
local siestahut_assets = { Asset("ANIM", "anim/siesta_canopy.zip"), }
local assets_item = { 
	Asset("ANIM", "anim/bag.zip"), 
	Asset( "IMAGE", "images/inventoryimages/bag1.tex" ), Asset( "ATLAS", "images/inventoryimages/bag1.xml" ), 
	Asset( "IMAGE", "images/inventoryimages/bag2.tex" ), Asset( "ATLAS", "images/inventoryimages/bag2.xml" ), 
	Asset( "IMAGE", "images/inventoryimages/bag3.tex" ), Asset( "ATLAS", "images/inventoryimages/bag3.xml" ), 
	Asset( "IMAGE", "images/inventoryimages/bag4.tex" ), Asset( "ATLAS", "images/inventoryimages/bag4.xml" ), 
	Asset( "IMAGE", "images/inventoryimages/bag5.tex" ), Asset( "ATLAS", "images/inventoryimages/bag5.xml" ), 
	Asset( "IMAGE", "images/inventoryimages/bag6.tex" ), Asset( "ATLAS", "images/inventoryimages/bag6.xml" ), 
}
local prefabs = {"collapse_big","bag",}
local prefabs_item = {"tent",}
------------------------------------------------------------------------------------------
local function PlaySleepLoopSoundTask(inst, stopfn)
	inst.SoundEmitter:PlaySound("dontstarve/common/tent_sleep")
end
local function stopsleepsound(inst)
	if inst.sleep_tasks ~= nil then
		for i, v in ipairs(inst.sleep_tasks) do v:Cancel() end
		inst.sleep_tasks = nil
	end
end
local function startsleepsound(inst, len)
	stopsleepsound(inst)
	inst.sleep_tasks = {
		inst:DoPeriodicTask(len, PlaySleepLoopSoundTask, 33 * FRAMES),
		inst:DoPeriodicTask(len, PlaySleepLoopSoundTask, 47 * FRAMES), }
end
------------------------------------------------------------------------------------------
local function ChangeToItem(inst)
	if not inst:HasTag("burnt") then
		inst:RemoveComponent("sleepingbag")
		if inst.components.finiteuses.current == 6 then
			local item = SpawnPrefab("bag6", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
		if inst.components.finiteuses.current == 5 then
			local item = SpawnPrefab("bag5", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
		if inst.components.finiteuses.current == 4 then
			local item = SpawnPrefab("bag4", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
		if inst.components.finiteuses.current == 3 then
			local item = SpawnPrefab("bag3", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
		if inst.components.finiteuses.current == 2 then
			local item = SpawnPrefab("bag2", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
		if inst.components.finiteuses.current == 1 then
			local item = SpawnPrefab("bag1", inst.linked_skinname, inst.skin_id) 
			if item ~= nil then
				item.Transform:SetPosition(inst.Transform:GetWorldPosition())
				item.AnimState:PlayAnimation("destroy_item")
				item.AnimState:PushAnimation("idle_item", true)
				item.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
			end
		end
	end
end
local function onhammered(inst, worker)
	if inst.components.burnable ~= nil and inst.components.burnable:IsBurning() then
        inst.components.burnable:Extinguish()
    end
    inst.components.lootdropper:DropLoot()
    local fx = SpawnPrefab("collapse_big")
    fx.Transform:SetPosition(inst.Transform:GetWorldPosition())
    fx:SetMaterial("wood")
    inst:Remove()
end
local function onhit(inst, worker)
	 if not inst:HasTag("burnt") then
        stopsleepsound(inst)
        inst.AnimState:PlayAnimation("hit")
        inst.AnimState:PushAnimation("idle", true)
    end
    if inst.components.sleepingbag ~= nil and inst.components.sleepingbag.sleeper ~= nil then
        inst.components.sleepingbag:DoWakeUp()
    end
end
------------------------------------------------------------------------------------------
local function onfinishedsound(inst)
	inst.SoundEmitter:PlaySound("dontstarve/common/tent_dis_twirl")
end
local function onfinished(inst)
	if not inst:HasTag("burnt") then
		stopsleepsound(inst)
		inst.AnimState:PlayAnimation("destroy")
		inst:ListenForEvent("animover", inst.Remove)
		inst.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
		inst.persists = false
		inst:DoTaskInTime(16 * FRAMES, onfinishedsound)
	end
end
local function onbuilt_tent(inst)
	inst.AnimState:PlayAnimation("place")
	inst.AnimState:PushAnimation("idle", true)
	inst.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
end
local function onbuilt_siestahut(inst)
    inst.AnimState:PlayAnimation("place")
    inst.AnimState:PushAnimation("idle", true)
    inst.SoundEmitter:PlaySound("dontstarve/common/lean_to_craft")
end
local function onignite(inst)
	inst.components.sleepingbag:DoWakeUp()
end
local function onwake(inst, sleeper, nostatechange)
	sleeper:RemoveEventCallback("onignite", onignite, inst)
	if inst.sleep_anim ~= nil then
		inst.AnimState:PushAnimation("idle", true)
		stopsleepsound(inst)
	end
	inst.components.finiteuses:Use()
end
local function onsleep(inst, sleeper)
	sleeper:ListenForEvent("onignite", onignite, inst)
	if inst.sleep_anim ~= nil then
		inst.AnimState:PlayAnimation(inst.sleep_anim, true)
		startsleepsound(inst, inst.AnimState:GetCurrentAnimationLength())
	end
end
local function temperaturetick(inst, sleeper)
	if sleeper.components.temperature ~= nil then
		if inst.is_cooling then
			if sleeper.components.temperature:GetCurrent() > TUNING.SLEEP_TARGET_TEMP_TENT then
				sleeper.components.temperature:SetTemperature(sleeper.components.temperature:GetCurrent() - TUNING.SLEEP_TEMP_PER_TICK)
			end
		elseif sleeper.components.temperature:GetCurrent() < TUNING.SLEEP_TARGET_TEMP_TENT then
			sleeper.components.temperature:SetTemperature(sleeper.components.temperature:GetCurrent() + TUNING.SLEEP_TEMP_PER_TICK)
		end
	end
end
local function OnDismantle(inst)
	ChangeToItem(inst)
	inst:Remove()
end
------------------------------------------------------------------------------------------
local function onsave(inst, data)
	if inst:HasTag("burnt") or (inst.components.burnable ~= nil and inst.components.burnable:IsBurning()) then
		data.burnt = true
	end
end
local function onload(inst, data)
	if data ~= nil and data.burnt then
		inst.components.burnable.onburnt(inst)
	end
end
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
local function common_fn(bank, build, icon, tag, onbuiltfn)
	local inst = CreateEntity()
	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.entity:AddMiniMapEntity()
	inst.entity:AddNetwork()

	MakeObstaclePhysics(inst, 1)

	inst:AddTag("tent")
	inst:AddTag("structure")
	if tag ~= nil then inst:AddTag(tag) end

	inst.AnimState:SetBank(bank)
	inst.AnimState:SetBuild(build)
	inst.AnimState:PlayAnimation("idle", true)

	inst.MiniMapEntity:SetIcon(icon)
	MakeSnowCoveredPristine(inst)
	inst.entity:SetPristine()

	if not TheWorld.ismastersim then return inst end

	inst:AddComponent("inspectable")
	inst:AddComponent("lootdropper")
	inst:AddComponent("workable")
	inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
	inst.components.workable:SetWorkLeft(4)
	inst.components.workable:SetOnFinishCallback(onhammered)
	inst.components.workable:SetOnWorkCallback(onhit)

	inst:AddComponent("finiteuses")
	inst.components.finiteuses:SetOnFinished(onfinished)

	inst:AddComponent("sleepingbag")
	inst.components.sleepingbag.onsleep = onsleep
	inst.components.sleepingbag.onwake = onwake
	inst.components.sleepingbag.health_tick = TUNING.SLEEP_HEALTH_PER_TICK
	inst.components.sleepingbag.dryingrate = math.max(0, -TUNING.SLEEP_WETNESS_PER_TICK / TUNING.SLEEP_TICK_PERIOD)
	inst.components.sleepingbag:SetTemperatureTickFn(temperaturetick)

	MakeSnowCovered(inst)
	inst:ListenForEvent("onbuilt", onbuiltfn)

	MakeLargeBurnable(inst, nil, nil, true)
	MakeMediumPropagator(inst)

	inst.OnSave = onsave 
	inst.OnLoad = onload
	MakeHauntableWork(inst)
	return inst
end
local function tent() 
	local inst = common_fn("tent", "tent", "tent.png", nil, onbuilt_tent)
	if not TheWorld.ismastersim then return inst end

	inst.sleep_anim = "sleep_loop"
	inst.components.sleepingbag.hunger_tick = TUNING.SLEEP_HUNGER_PER_TICK
	--inst.is_cooling = false
	
	inst:AddComponent("portablestructure")
	inst.components.portablestructure:SetOnDismantleFn(OnDismantle)
	inst.components.finiteuses:SetMaxUses(TUNING.TENT_USES)
	inst.components.finiteuses:SetUses(TUNING.TENT_USES)
	return inst
end
local function siestahut()
	local inst = common_fn("siesta_canopy", "siesta_canopy", "siestahut.png", "siestahut", onbuilt_siestahut)
	if not TheWorld.ismastersim then return inst end

	inst.components.sleepingbag:SetSleepPhase("day")
	--inst.sleep_anim = nil
	inst.components.sleepingbag.hunger_tick = TUNING.SLEEP_HUNGER_PER_TICK / 3
	inst.is_cooling = true

	inst.components.finiteuses:SetMaxUses(TUNING.SIESTA_CANOPY_USES)
	inst.components.finiteuses:SetUses(TUNING.SIESTA_CANOPY_USES)
    return inst
end
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
local function ondeploy6(inst, pt, deployer)
	local mb6 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb6 ~= nil then
		mb6.Physics:SetCollides(false)
		mb6.Physics:Teleport(pt.x, 0, pt.z)
		mb6.Physics:SetCollides(true)
		mb6.AnimState:PlayAnimation("place")
		mb6.AnimState:PushAnimation("idle", true)
		mb6.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb6.components.finiteuses:SetUses(6) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb6)
	end
end
local function ondeploy5(inst, pt, deployer)
	local mb5 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb5 ~= nil then
		mb5.Physics:SetCollides(false)
		mb5.Physics:Teleport(pt.x, 0, pt.z)
		mb5.Physics:SetCollides(true)
		mb5.AnimState:PlayAnimation("place")
		mb5.AnimState:PushAnimation("idle", true)
		mb5.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb5.components.finiteuses:SetUses(5) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb5)
	end
end
local function ondeploy4(inst, pt, deployer)
	local mb4 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb4 ~= nil then
		mb4.Physics:SetCollides(false)
		mb4.Physics:Teleport(pt.x, 0, pt.z)
		mb4.Physics:SetCollides(true)
		mb4.AnimState:PlayAnimation("place")
		mb4.AnimState:PushAnimation("idle", true)
		mb4.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb4.components.finiteuses:SetUses(4) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb4)
	end
end
local function ondeploy3(inst, pt, deployer)
	local mb3 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb3 ~= nil then
		mb3.Physics:SetCollides(false)
		mb3.Physics:Teleport(pt.x, 0, pt.z)
		mb3.Physics:SetCollides(true)
		mb3.AnimState:PlayAnimation("place")
		mb3.AnimState:PushAnimation("idle", true)
		mb3.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb3.components.finiteuses:SetUses(3) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb3)
	end
end
local function ondeploy2(inst, pt, deployer)
	local mb2 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb2 ~= nil then
		mb2.Physics:SetCollides(false)
		mb2.Physics:Teleport(pt.x, 0, pt.z)
		mb2.Physics:SetCollides(true)
		mb2.AnimState:PlayAnimation("place")
		mb2.AnimState:PushAnimation("idle", true)
		mb2.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb2.components.finiteuses:SetUses(2) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb2)
	end
end
local function ondeploy1(inst, pt, deployer)
	local mb1 = SpawnPrefab("tent", inst.linked_skinname, inst.skin_id )
	if mb1 ~= nil then
		mb1.Physics:SetCollides(false)
		mb1.Physics:Teleport(pt.x, 0, pt.z)
		mb1.Physics:SetCollides(true)
		mb1.AnimState:PlayAnimation("place")
		mb1.AnimState:PushAnimation("idle", true)
		mb1.SoundEmitter:PlaySound("dontstarve/common/tent_craft")
		mb1.components.finiteuses:SetUses(1) --inst.components.finiteuses:GetUses()
		inst:Remove()
		--PreventCharacterCollisionsWithPlacedObjects(mb1)
	end
end
local function common_item(bank, build, ondeployfn)
	local inst = CreateEntity()
	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.entity:AddNetwork()
	
	MakeInventoryPhysics(inst)

	inst.AnimState:SetBank(bank)
	inst.AnimState:SetBuild(build)
	inst.AnimState:PlayAnimation("idle_item", true)
	
	MakeInventoryFloatable(inst, "med", 0.1, 0.8)
	
	inst.entity:SetPristine()
	if not TheWorld.ismastersim then return inst end

	inst:AddComponent("inspectable")
	inst:AddComponent("inventoryitem")
	inst:AddComponent("finiteuses")
	inst:AddComponent("deployable")
	inst.components.deployable.ondeploy = ondeployfn
	
	inst:AddComponent("hauntable")
	inst.components.hauntable:SetHauntValue(TUNING.HAUNT_TINY)
	
	MakeLargeBurnable(inst, nil, nil, true)
	MakeMediumPropagator(inst)

	inst.OnSave = onsave 
	inst.OnLoad = onload
	return inst
end
local function bag6()
	local inst = common_item("bag", "bag", ondeploy6)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag6"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag6.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(6)
	return inst
end
local function bag5()
	local inst = common_item("bag", "bag", ondeploy5)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag5"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag5.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(5)
	return inst
end
local function bag4()
	local inst = common_item("bag", "bag", ondeploy4)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag4"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag4.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(4)
	return inst
end
local function bag3()
	local inst = common_item("bag", "bag", ondeploy3)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag3"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag3.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(3)
	return inst
end
local function bag2()
	local inst = common_item("bag", "bag", ondeploy2)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag2"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag2.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(2)
	return inst
end
local function bag1()
	local inst = common_item("bag", "bag", ondeploy1)
	if not TheWorld.ismastersim then return inst end
	inst.components.inventoryitem.imagename = "bag1"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/bag1.xml"
	inst.components.finiteuses:SetMaxUses(6)
	inst.components.finiteuses:SetUses(1)
	return inst
end
return Prefab("tent", tent, tent_assets, prefabs),
	MakePlacer("tent_placer", "tent", "tent", "idle"),
	Prefab("siestahut", siestahut, siestahut_assets),
	MakePlacer("siestahut_placer", "siesta_canopy", "siesta_canopy", "idle"),
	
	Prefab("bag6", bag6, assets_item, prefabs_item),	
		MakePlacer("bag6_placer", "tent", "tent", "idle"),
	Prefab("bag5", bag5, assets_item, prefabs_item),
		MakePlacer("bag5_placer", "tent", "tent", "idle"),
	Prefab("bag4", bag4, assets_item, prefabs_item),	
		MakePlacer("bag4_placer", "tent", "tent", "idle"),
	Prefab("bag3", bag3, assets_item, prefabs_item),
		MakePlacer("bag3_placer", "tent", "tent", "idle"),
	Prefab("bag2", bag2, assets_item, prefabs_item),
		MakePlacer("bag2_placer", "tent", "tent", "idle"),	
	Prefab("bag1", bag1, assets_item, prefabs_item),
		MakePlacer("bag1_placer", "tent", "tent", "idle")