require "prefabutil"

--The test to see if a boat can be built in a certain position is defined in the builder component Builder:CanBuildAtPoint

local prefabs =
{
	"rowboat_wake",
	"boat_hit_fx",
	"boat_hit_fx_raft_log",
	"boat_hit_fx_raft_bamboo",
	"boat_hit_fx_rowboat",
	"boat_hit_fx_cargoboat",
	"boat_hit_fx_armoured",
	"flotsam_armoured",
	"flotsam_bamboo",
	"flotsam_cargo",
	"flotsam_lograft",
	"flotsam_rowboat",
	"flotsam_surfboard",
	"woodlegs_boatcannon",
	"woodlegssail",
	"woodlegs_cannonshot",
}

local soundprefix = "researchlab"
local name = "researchlab"

local surfboardassets =
{
	--自己改的
    Asset("ANIM", "anim/sword_3.zip"),
    Asset("ANIM", "anim/swap_sword_3.zip"),
	Asset("ANIM", "anim/toso_sword_fly.zip"),	
	
	Asset("ANIM", "anim/raft_surfboard_build.zip"),
	Asset("ANIM", "anim/boat_hud_raft.zip"),
	Asset("ANIM", "anim/boat_inspect_raft.zip"),
	Asset("ANIM", "anim/flotsam_surfboard_build.zip"),
	Asset("MINIMAP_IMAGE", "surfboard"),
	Asset("IMAGE","images/inventoryimages/sword_3.tex"),
	Asset("ATLAS","images/inventoryimages/sword_3.xml")
}

local function boat_perish(inst)

	--inst:PushEvent("death", {})
	--GetWorld():PushEvent("entity_death", {inst = inst})

	if inst.components.drivable.driver then

		local driver = inst.components.drivable.driver

		driver.components.driver:OnDismount(true)

		driver.components.health:Kill("drowning")

		inst.SoundEmitter:PlaySound(inst.sinksound)
		--driver:PushEvent("death", {cause="drowning"})
		--GetWorld():PushEvent("entity_death", {inst = driver, cause="drowning"})
		if inst.components.container then
			inst.components.container:DropEverything()
		end
		inst:Remove()
	end
end



local function onhit(inst, worker)
	inst.AnimState:PlayAnimation("hit")
	inst.AnimState:PushAnimation("run_loop", true)
end

local function onhammered(inst, worker)
	inst.components.lootdropper:DropLoot()
    if inst.components.container then
        inst.components.container:DropEverything()
    end	
	SpawnPrefab("collapse_small").Transform:SetPosition(inst.Transform:GetWorldPosition())
	inst.SoundEmitter:PlaySound("dontstarve/common/destroy_wood")
	inst:Remove()
end

local function onmounted(inst)
	--print("I'm getting mounted!")
	inst:RemoveComponent("workable")
end

local function ondismounted(inst)
	inst:AddComponent("workable")
	inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
    inst.components.workable:SetWorkLeft(4)
    inst.components.workable:SetOnFinishCallback(onhammered)
	inst.components.workable:SetOnWorkCallback(onhit)
end

local function onopen(inst)
	if inst.components.drivable.driver == nil then
		inst.SoundEmitter:PlaySound("dontstarve_DLC002/common/HUD_boat_inventory_open")
	end
end

local function onclose(inst)
	if inst.components.drivable.driver == nil then
		inst.SoundEmitter:PlaySound("dontstarve_DLC002/common/HUD_boat_inventory_close")
	end
end

local function setupcontainer(inst, slots, bank, build, inspectslots, inspectbank, inspectbuild, inspectboatbadgepos, inspectboatequiproot)
	inst:AddComponent("container")
	inst.components.container:SetNumSlots(#slots)
	inst.components.container.type = "boat"
	inst.components.container.side_align_tip = -500
	inst.components.container.canbeopened = false
	inst.components.container.onopenfn = onopen
	inst.components.container.onclosefn = onclose

	inst.components.container.widgetslotpos = slots
	inst.components.container.widgetanimbank = bank
	inst.components.container.widgetanimbuild = build
	inst.components.container.widgetboatbadgepos = Vector3(0, 40, 0)
	inst.components.container.widgetequipslotroot = Vector3(-80, 40, 0)


	local boatwidgetinfo = {}
	boatwidgetinfo.widgetslotpos = inspectslots
	boatwidgetinfo.widgetanimbank = inspectbank
	boatwidgetinfo.widgetanimbuild = inspectbuild
	boatwidgetinfo.widgetboatbadgepos = inspectboatbadgepos
	boatwidgetinfo.widgetpos = Vector3(200, 0, 0)
	boatwidgetinfo.widgetequipslotroot = inspectboatequiproot
	inst.components.container.boatwidgetinfo = boatwidgetinfo
end




local function commonfn(Sim)
	local inst = CreateEntity()
	local trans = inst.entity:AddTransform()
	trans:SetFourFaced()
	inst.no_wet_prefix = true

	inst:AddTag("boat")

	local anim = inst.entity:AddAnimState()

	inst.entity:AddSoundEmitter()

	inst.entity:AddPhysics()
	inst.Physics:SetCylinder(0.25,2)

	inst:AddComponent("inspectable")
	inst:AddComponent("drivable")

	inst.waveboost = TUNING.WAVEBOOST

	inst.sailmusic = "sailing"

	inst:AddComponent("rowboatwakespawner")

	inst:AddComponent("boathealth")
	inst.components.boathealth:SetDepletedFn(boat_perish)

    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("lootdropper")

    inst:AddComponent("repairable")
    inst.components.repairable.repairmaterial = "boat"

    inst.components.repairable.onrepaired = function(inst, doer, repair_item)
		if inst.SoundEmitter then
			inst.SoundEmitter:PlaySound("dontstarve_DLC002/common/boatrepairkit")
		end
	end

    inst:ListenForEvent("mounted", onmounted)
    inst:ListenForEvent("dismounted", ondismounted)

    inst.onhammered = onhammered
 
 	inst:AddComponent("flotsamspawner")

	return inst
end



local function pickupfn(inst, guy)
 --local player = GetPlayer() 
	local board = SpawnPrefab("toso_surfboard")
	local suiyi = SpawnPrefab("surfboard_item_toso")
	guy.components.inventory:GiveItem(board)
	guy.components.inventory:GiveItem(suiyi)
	--board.components.pocket:GiveItem("surfboard_item_toso", inst)
				--local pande = player.components.inventory
			--if player then
			--local suiyi = SpawnPrefab("surfboard_item_toso")
			--inst.components.inventory:GiveItem(suiyi)
				--player:GiveItem("surfboard_item_toso")
			--end
	
	return true
end

local function surfboardfn(sim)
	local inst = commonfn(sim)

	setupcontainer(inst, {}, "boat_hud_raft", "boat_hud_raft", {}, "boat_inspect_raft", "boat_inspect_raft", {x=0,y=5}, {})

	inst.AnimState:SetBank("toso_sword_fly")
	inst.AnimState:SetBuild("toso_sword_fly")
	inst.AnimState:PlayAnimation("run_loop", true)

	--local minimap = inst.entity:AddMiniMapEntity()
	--minimap:SetPriority( 5 )
	--minimap:SetIcon("surfboard.png")
	inst.perishtime = TUNING.SURFBOARD_PERISHTIME
	inst.components.boathealth.maxhealth = 460
	inst.components.boathealth:SetHealth(TUNING.460, inst.perishtime)

	inst.landsound = "dontstarve_DLC002/common/boatjump_land_wood"
	inst.sinksound = "dontstarve_DLC002/common/boat_sinking_log_cargo"
	inst.sailsound = "common/surfboard_sail_LP"
	inst.sailmusic = "surfing"

	inst.components.boathealth.damagesound = "dontstarve_DLC002/common/surfboard_damage"

	inst.components.drivable.sanitydrain = TUNING.SURFBOARD_SANITY_DRAIN
	inst.components.drivable.runspeed = TUNING.SURFBOARD_SPEED
	inst.components.drivable.hitmoisturerate = TUNING.SURFBOARD_HITMOISTURERATE
	inst.components.drivable.maprevealbonus = TUNING.MAPREVEAL_RAFT_BONUS
	inst.components.drivable.sailloopanim = "surf_loop"
	inst.components.drivable.sailstartanim = "surf_pre"
	inst.components.drivable.sailstopanim = "surf_pst"
	inst.components.drivable.overridebuild = "toso_sword_fly"
	inst.components.drivable.flotsambuild = "flotsam_surfboard_build"
	inst.components.drivable.creaksound = "dontstarve_DLC002/common/boat_creaks"
	inst.components.drivable.alwayssail = true

	inst.components.flotsamspawner.flotsamprefab = "flotsam_surfboard"

	inst.waveboost = TUNING.SURFBOARD_WAVEBOOST
	inst.wavesanityboost = TUNING.SURFBOARD_WAVESANITYBOOST

	inst:AddComponent("characterspecific")
    inst.components.characterspecific:SetOwner("toso")

	inst:AddComponent("pickupable")
	inst.components.pickupable:SetOnPickupFn(pickupfn)
	inst:SetInherentSceneAltAction(ACTIONS.RETRIEVE)

	return inst
end

local function ondeploy(inst, pt, deployer)
	print("ondeploy")
	local board = inst.components.pocket:RemoveItem("toso_surfboard") or SpawnPrefab("toso_surfboard")

	if board then
		pt = Vector3(pt.x, 0, pt.z)
		board.Physics:SetCollides(false)
		board.Physics:Teleport(pt.x, pt.y, pt.z)
		board.Physics:SetCollides(true)
		inst:Remove()
	end
end

local function deploytest(inst, pt)

	------------------------------------------------------
	-- MAKE SURE THIS TEST MATCHES THE BUILDER.LUA TEST --
	------------------------------------------------------
	local ground = GetWorld()
    local tile = GROUND.GRASS
    if ground and ground.Map then
        tile = ground.Map:GetTileAtPoint(pt:Get())
    end

    local onWater = ground.Map:IsWater(tile)

    -- ugly hack for deloying walani's surfboard from a boat
    local boating = GetPlayer().components.driver.driving
    -- local boating = inst.components.inventoryitem and inst.components.inventoryitem.owner
    -- 				and inst.components.inventoryitem.owner.components.driver and inst.components.inventoryitem.owner.components.driver.driving


    if boating then
    	return onWater
	else
    	local x, y, z = pt:Get()
		local testTile = inst:GetCurrentTileType(x, y, z)--ground.Map:GetTileAtPoint(x , y, z)
		local isShore = ground.Map:IsShore(testTile) --testTile == GROUND.OCEAN_SHORE --ground.Map:IsWater(testTile)

		local maxBuffer = 2
		local nearShore = false
		testTile = inst:GetCurrentTileType(x + maxBuffer, y, z)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x - maxBuffer, y, z)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x , y, z + maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x , y, z - maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore

		testTile = inst:GetCurrentTileType(x + maxBuffer, y, z + maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x - maxBuffer, y, z + maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x + maxBuffer , y, z - maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore
		testTile = inst:GetCurrentTileType(x - maxBuffer , y, z - maxBuffer)
		nearShore = (not ground.Map:IsWater(testTile)) or nearShore

		local minBuffer = 0.5
		local tooClose = false
		testTile = inst:GetCurrentTileType(x + minBuffer, y, z)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x - minBuffer, y, z)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x , y, z + minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x , y, z - minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose

		testTile = inst:GetCurrentTileType(x + minBuffer, y, z + minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x - minBuffer, y, z + minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x + minBuffer , y, z - minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose
		testTile = inst:GetCurrentTileType(x - minBuffer, y, z - minBuffer)
		tooClose = (not ground.Map:IsWater(testTile)) or tooClose

		return isShore and nearShore and not tooClose
	end
end

local function surfboard_ondropped(inst)
	--If this is a valid place to be deployed, auto deploy yourself.
	if inst.components.deployable and inst.components.deployable:CanDeploy(inst:GetPosition()) then
		inst.components.deployable:Deploy(inst:GetPosition(), inst)
	end
end

local function surfboarditemfn(Sim)
	local inst = CreateEntity()

	local minimap = inst.entity:AddMiniMapEntity()
	minimap:SetPriority( 5 )
	minimap:SetIcon("sword_3.png")

	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	MakeInventoryPhysics(inst)

	inst:AddTag("boat")

	inst.AnimState:SetBank("sword_3")
	inst.AnimState:SetBuild("sword_3")
	inst.AnimState:PlayAnimation("idle")

	inst:AddComponent("inspectable")
	inst:AddComponent("inventoryitem")
	inst.components.inventoryitem.imagename = "sword_3"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/sword_3.xml"
	inst.components.inventoryitem:SetOnDroppedFn(surfboard_ondropped)

	inst:AddComponent("pocket")

	inst:AddComponent("deployable")
	inst.components.deployable.ondeploy = ondeploy
	inst.components.deployable.placer = "surfboard_placer"
	inst.components.deployable.test = deploytest
	inst.components.deployable.deploydistance = 3


	inst:AddComponent("characterspecific")
    inst.components.characterspecific:SetOwner("toso")

	return inst
end


return Prefab( "common/objects/toso_surfboard", surfboardfn, surfboardassets, prefabs),
	   Prefab("common/surfboard_item_toso", surfboarditemfn, surfboardassets, prefabs),
	   MakePlacer( "common/surfboard_placer", "toso_sword_fly", "toso_sword_fly", "run_loop", false, false, false, nil, nil, nil, nil, false, true)
