local assets =
{
	Asset("ANIM", "anim/teleporter_worm.zip"),
	Asset("ANIM", "anim/teleporter_sickworm_build.zip"),
	Asset("SOUND", "sound/common.fsb"),
	Asset("MINIMAP_IMAGE", "wormhole_sick"),
}

local rocksspawns = 
{
	rocks                  = 75,
	flint                  = 75,
	goldnugget             = 20,
	nitre                  = 20,
	marble                 = 20,	
	houndstooth            = 5,	
	redgem                 = 3,
	bluegem                = 3,
	thulecite_pieces       = 3,
	beardhair              = 3,
	lightbulb              = 3,
	guano                  = 3,
	wormlight              = 3,
	spider                 = 2,
	spider_warrior         = 2,
	spider_spitter         = 2,
	spider_hider           = 2,
	spider_dropper         = 2,
	bunnyman               = 2,
	slurtle                = 2,
	snurtle                = 2,
	purplegem              = 1,
	greengem               = 1,
	orangegem              = 1,
	yellowgem              = 1,
	gears                  = 1,
	thulecite              = 1,
}

local rocksspawns_DLC = 
{
	rocks                  = 75,
	flint                  = 75,
	goldnugget             = 20,
	nitre                  = 20,
	marble                 = 20,	
	boneshard              = 10,
	mole                   = 10,
	houndstooth            = 5,		
	redgem                 = 3,
	bluegem                = 3,
	thulecite_pieces       = 3,
	beardhair              = 3,
	lightbulb              = 3,
	guano                  = 3,
	wormlight              = 3,	
	spider                 = 2,
	spider_warrior         = 2,
	spider_spitter         = 2,
	spider_hider           = 2,
	spider_dropper         = 2,
	bunnyman               = 2,
	slurtle                = 2,
	snurtle                = 2,
	purplegem              = 1,
	greengem               = 1,
	orangegem              = 1,
	yellowgem              = 1,
	gears                  = 1,
	thulecite              = 1,
}

local bigspawns = 
{
	rock1                   = 75,
	rock2                   = 75,
	rock_flintless          = 75,
	stalagmite_full         = 25,
	stalagmite_med          = 25,
	stalagmite_low          = 25,
	stalagmite_tall_full    = 25,
	stalagmite_tall_med     = 25,
	stalagmite_tall_low     = 25,
	spiderhole              = 25,
	slurtlehole             = 25,
	houndbone               = 25,
	houndmound              = 25,
	skeleton                = 25,
	worm                    = 25,
	rabbithouse             = 10,
}

function GetSpawnPoint(pt, rad)
    local theta = math.random() * 2 * PI
    local radius = math.random(3,12) 	
	local result_offset = FindValidPositionByFan(theta, radius, 12, function(offset)
		local ground = GetWorld()
        local spawn_point = pt + offset
        if not (ground.Map and ground.Map:GetTileAtPoint(spawn_point.x, spawn_point.y, spawn_point.z) == GROUND.IMPASSABLE or ground.Map:GetTileAtPoint(spawn_point.x, spawn_point.y, spawn_point.z) > GROUND.UNDERGROUND) then
			return true
        end
		return false
    end)
	if result_offset then
		return pt + result_offset
	end
end    
	
local function DebrisFall(inst)
	local pt = Point(inst.Transform:GetWorldPosition())
	if inst.components.combat then
		inst.Physics:SetDamping(0)
		inst.Physics:SetMass(100)
        inst.Physics:SetMotorVel(0,-20+math.random()*10,0)	
	end	
	if pt.y < 2 then
		inst.Physics:SetMotorVel(0,0,0)
    end
	if pt.y <= .2 then
		local ents = TheSim:FindEntities(pt.x, 0, pt.z, 2, nil, {'smashable'})
	    for k,v in pairs(ents) do
	    	if v and v.components.combat and v ~= inst then
	    		v.components.combat:GetAttacked(inst, 20, nil)
	    	end
	   	end
	   	inst.Physics:SetDamping(0.9)	
		if inst.updatetask then
			inst.updatetask:Cancel()
			inst.updatetask = nil
		end	
		local pos = Vector3(inst.Transform:GetWorldPosition())
		local tile = GetWorld().Map:GetTileAtPoint(pos.x, pos.y, pos.z)
		if tile == GROUND.IMPASSABLE then
			inst.SoundEmitter:PlaySound("dontstarve/common/stone_drop")
			local pt = Vector3(inst.Transform:GetWorldPosition())
			local breaking = SpawnPrefab("ground_chunks_breaking")
			breaking.Transform:SetPosition(pt.x, 0, pt.z)
			inst:Remove()
		else	
			if inst.components.combat then
				inst.Physics:Stop()
				inst.Physics:SetDamping(5)
				inst.Physics:Teleport(pt.x,pt.y,pt.z)
			elseif math.random() < 0.80  then
				inst.SoundEmitter:PlaySound("dontstarve/common/stone_drop")
				local pt = Vector3(inst.Transform:GetWorldPosition())
				local breaking = SpawnPrefab("ground_chunks_breaking")
				breaking.Transform:SetPosition(pt.x, 0, pt.z)
				inst:Remove()
			end
		end
	end
end	

local function DebrisInitialize(inst)
	inst.updatetask = inst:DoPeriodicTask(1*FRAMES,DebrisFall,1)	
end

local function SpawnDebris(inst)
	local numrocks = math.random(1,9)
	for k = 1, numrocks do
		local rocks_prefab
		if (IsDLCEnabled(CAPY_DLC) or IsDLCEnabled(REIGN_OF_GIANTS)) then
			rocks_prefab = weighted_random_choice(rocksspawns_DLC)
		else
			rocks_prefab = weighted_random_choice(rocksspawns)
		end
		local rocks = SpawnPrefab(rocks_prefab) 
		if rocks.components.combat then
			if rocks.prefab == "mole" then
				rocks.sg:GoToState("fall")
			end
			local pos = Vector3(inst.Transform:GetWorldPosition())
			local spawn_point = GetSpawnPoint(pos)	
			rocks.Physics:Teleport(spawn_point.x,35,spawn_point.z)	
			inst:DoTaskInTime(0.5, function(inst) DebrisInitialize(rocks) end)
		else
			rocks.entity:AddPhysics()
			rocks.entity:AddSoundEmitter()
			rocks.Transform:SetPosition(inst:GetPosition():Get())
			local vx, vy, vz = rocks.Physics:GetVelocity()
			rocks.Physics:SetVel(math.random(-15,15), math.random(20,35), math.random(-15,15))
			inst:DoTaskInTime(0.5, function(inst) DebrisInitialize(rocks) end)
		end
	end
end	

local function StuffFall(inst)
	local pt = Point(inst.Transform:GetWorldPosition())
	if inst.components.combat then
		inst.Physics:SetDamping(0)
		inst.Physics:SetMass(100)
        inst.Physics:SetMotorVel(0,-20+math.random()*10,0)	
	end	
	if pt.y < 2 then
		inst.Physics:SetMotorVel(0,0,0)
    end
	if pt.y <= .2 then
	
		local ents = TheSim:FindEntities(pt.x, 0, pt.z, 5, nil, {'smashable'})
	    for k,v in pairs(ents) do
			if v and v.components.combat and v ~= inst then
				v.components.combat:GetAttacked(inst, 70, nil)
			end
	   	end
		
	   	inst.Physics:SetDamping(0.9)	
		if inst.updatetask then
			inst.updatetask:Cancel()
			inst.updatetask = nil
		end			
		local pos = Vector3(inst.Transform:GetWorldPosition())
		local tile = GetWorld().Map:GetTileAtPoint(pos.x, pos.y, pos.z)
		if not inst.components.combat then
			ChangeToObstaclePhysics(inst)	
		end 
		if tile == GROUND.IMPASSABLE then
			inst.SoundEmitter:PlaySound("dontstarve/common/stone_drop")
			local pt = Vector3(inst.Transform:GetWorldPosition())
			local breaking = SpawnPrefab("ground_chunks_breaking")
			breaking.Transform:SetPosition(pt.x, 0, pt.z)
			inst:Remove()
		else	
			if inst.components.combat then
				inst.Physics:Stop()
				inst.Physics:SetDamping(5)
				inst.Physics:Teleport(pt.x,pt.y,pt.z)
			elseif math.random() < 0.33 then
				if inst.components.workable and inst.components.workable.workleft > 0 then
					SpawnPrefab("collapse_small").Transform:SetPosition(inst:GetPosition():Get())
					inst.components.workable:Destroy(inst)
				else 
					SpawnPrefab("collapse_small").Transform:SetPosition(inst:GetPosition():Get())
					inst:Remove()
				end
			end
		end		
	end
end	

local function StuffInitialize(inst)
	inst.updatetask = inst:DoPeriodicTask(1*FRAMES,StuffFall,1)	
end

local function SpawnCaveStuff(inst)
	local stuff_prefab = weighted_random_choice(bigspawns)
	local stuff = SpawnPrefab(stuff_prefab)
	stuff.entity:AddPhysics()
	stuff.entity:AddSoundEmitter()
	if stuff.components.combat then
		local pos = Vector3(inst.Transform:GetWorldPosition())
		local spawn_point = GetSpawnPoint(pos)	
		stuff.Physics:Teleport(spawn_point.x,35,spawn_point.z)	
		inst:DoTaskInTime(0.4, function(inst) StuffInitialize(stuff) end)
		inst:DoTaskInTime(0.5, function(inst) stuff.Physics:CollidesWith(COLLISION.WORLD) end)
	else
		if stuff.prefab == "houndbone" then
			MakeInventoryPhysics(stuff)
		end
		stuff.Physics:SetMass(1)	
		stuff.Transform:SetPosition(inst:GetPosition():Get())
		local vx, vy, vz = stuff.Physics:GetVelocity()
		stuff.Physics:SetVel(math.random(-8,8), math.random(40,70), math.random(-8,8))
		inst:DoTaskInTime(0.4, function(inst) StuffInitialize(stuff) end)
		inst:DoTaskInTime(0.5, function(inst) stuff.Physics:CollidesWith(COLLISION.WORLD) end)
	end	
	if math.random() < 0.50 then
		SpawnDebris(inst)
	end
end

local function GiantWormHoleInitialize(inst)
	inst.updatetask = inst:DoPeriodicTask(1,SpawnCaveStuff,1)	
end

local function fn(Sim)
	local inst = CreateEntity()
	local trans = inst.entity:AddTransform()
	local anim = inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.Transform:SetScale(3.5, 3.5, 3.5)
	
	local minimap = inst.entity:AddMiniMapEntity()
	minimap:SetIcon( "wormhole_sick.png" )

    anim:SetBank("teleporter_worm")
	anim:SetBuild("teleporter_sickworm_build")
	anim:PlayAnimation("idle_loop", true)
	anim:SetLayer(LAYER_BACKGROUND)
	anim:SetSortOrder(3)  

	inst:AddTag("giantwormhole")
	
	inst:AddComponent("inspectable")
	--inst:DoPeriodicTask(3, function(inst)
	inst:DoTaskInTime(3, function(inst)
		inst.AnimState:PlayAnimation("cough")
		inst.AnimState:PushAnimation("idle_loop", true)
		inst:DoTaskInTime(6*FRAMES, function(inst) 	
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_cough") 
			SpawnDebris(inst)
		end)
		
		inst:DoTaskInTime(18*FRAMES, function(inst) 
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_cough") 
			SpawnDebris(inst)
		end)

		inst:DoTaskInTime(5, function(inst) 
			inst.AnimState:PlayAnimation("open_pre")
			inst.AnimState:PushAnimation("open_loop", true)
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/open", "wormhole_opening")
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/idle", "wormhole_open")	
		end)	
		
		inst:DoTaskInTime(6.5, function(inst) 
			TheCamera:Shake("FULL", 35, 0.02, 3, 75)
			inst.SoundEmitter:PlaySound("dontstarve/cave/earthquake", "earthquake")
			inst.SoundEmitter:SetParameter("earthquake", "intensity", 1)
			GiantWormHoleInitialize(inst)
		end)
		
		inst:DoTaskInTime(41.5, function(inst) 
			inst.SoundEmitter:KillSound("earthquake")
			if inst.updatetask then
				inst.updatetask:Cancel()
				inst.updatetask = nil
			end	
		end)
		
		inst:DoTaskInTime(43, function(inst) 
			inst.AnimState:PlayAnimation("open_pst")
			inst.AnimState:PushAnimation("idle_loop", true)
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/close", "wormhole_closing")
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/idle", "wormhole_open")	
		end)

		inst:DoTaskInTime(45, function(inst) 
			inst.AnimState:PlayAnimation("death")
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_die")
			inst:DoTaskInTime(39*FRAMES, function(inst) 
				inst.SoundEmitter:KillSound("wormhole_opening")
				inst.SoundEmitter:KillSound("wormhole_open")
				inst.SoundEmitter:KillSound("wormhole_closing")
				inst.SoundEmitter:KillSound("wormhole_open")
				inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_splat") 
				TheCamera:Shake("FULL", 1, 0.02, 3, 75)
				local dust = SpawnPrefab("small_puff")
                dust.Transform:SetPosition(inst:GetPosition():Get())
                dust.Transform:SetScale(7,7,7)
                local dust = SpawnPrefab("small_puff")
                dust.Transform:SetPosition(inst:GetPosition():Get())
                dust.Transform:SetScale(5,5,5)
				local dust = SpawnPrefab("collapse_small")
                dust.Transform:SetPosition(inst:GetPosition():Get())
                dust.Transform:SetScale(4,4,4)
				local pt = inst:GetPosition()
				local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, 6)
				for k,v in pairs(ents) do
					if v.components.combat and v ~= inst and not v:HasTag("shadow") then
						v.components.combat:GetAttacked(inst, 750)
					elseif v.components.workable and v.components.workable.workleft > 0 then
						SpawnPrefab("collapse_small").Transform:SetPosition(v:GetPosition():Get())
						v.components.workable:Destroy(inst)		
					end
				end	
				inst:Remove()
			end)
		end)
	end)
	
	inst.OnLoad = function(inst, data)    
		inst.AnimState:PlayAnimation("death")
		inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_die")
		inst:DoTaskInTime(39*FRAMES, function(inst) 
			inst.SoundEmitter:KillSound("wormhole_opening")
			inst.SoundEmitter:KillSound("wormhole_open")
			inst.SoundEmitter:KillSound("wormhole_closing")
			inst.SoundEmitter:KillSound("wormhole_open")
			inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/sick_splat") 
			TheCamera:Shake("FULL", 1, 0.02, 3, 75)
			local dust = SpawnPrefab("small_puff")
			dust.Transform:SetPosition(inst:GetPosition():Get())
			dust.Transform:SetScale(7,7,7)
			local dust = SpawnPrefab("small_puff")
			dust.Transform:SetPosition(inst:GetPosition():Get())
			dust.Transform:SetScale(5,5,5)
			local dust = SpawnPrefab("collapse_small")
			dust.Transform:SetPosition(inst:GetPosition():Get())
			dust.Transform:SetScale(4,4,4)
			local pt = inst:GetPosition()
			local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, 6)
			for k,v in pairs(ents) do
				if v.components.combat and v ~= inst and not v:HasTag("shadow") then
					v.components.combat:GetAttacked(inst, 750)
				elseif v.components.workable and v.components.workable.workleft > 0 then
					SpawnPrefab("collapse_small").Transform:SetPosition(v:GetPosition():Get())
					v.components.workable:Destroy(inst)		
				end
			end	
			inst:Remove()
		end)
	end
    return inst
end

STRINGS.NAMES.GIANTWORMHOLE = "Giant Stone Worm"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.GIANTWORMHOLE = "I guess it's time to run!"

return Prefab("common/inventory/giantwormhole", fn, assets) 