_G = GLOBAL

if not _G.TheNet:GetIsServer() then return end

local function ExpandFn(root, fn, exp)
	local old = root[fn]
	root[fn] = function(...)
		old(...)
		exp(...)
	end
	return root[fn]
end

local function GetDistanceDelay(inst, target, min, max, low, high)
	return _G.Remap(math.sqrt(inst:GetDistanceSqToInst(target)), min, max, low or 0, high or 1)
end

-- Призываем к сражению! --

AddPrefabPostInit("horn", function(inst)
	local function SpawnFuelFX(inst)
    	if not inst.components.inventoryitem:IsHeld() and inst:HasTag("charged") and inst.fuelfx == nil then
			local fx = _G.SpawnPrefab("nightlight_flame"); inst.fuelfx = fx
			fx:RemoveComponent("fuelfx"); fx.AnimState:PlayAnimation("level1", true)
			fx.entity:AddFollower():FollowSymbol(inst.GUID, "horn01", 110, -60, 0)
		end
	end

	local function OnPutInInventory(inst)
		if inst.fuelfx ~= nil then
			inst.fuelfx:Remove()
			inst.fuelfx = nil
		end
	end

	inst.components.inventoryitem:SetOnDroppedFn(SpawnFuelFX)
    inst.components.inventoryitem:SetOnPutInInventoryFn(OnPutInInventory)

	--------------------------------------------------------------------------

	ExpandFn(inst.components.instrument, "onheard",
	function(inst, musician, instrument)
		if instrument:HasTag("charged") and inst:HasTag("player") then
			local time = GetDistanceDelay(inst, musician, 0, instrument.components.instrument.range, 0.75, 2.5 + math.random())
			inst:DoTaskInTime(time, function()
				if inst.components.debuffable ~= nil and inst.components.debuffable:IsEnabled() and
				not (inst.components.health ~= nil and inst.components.health:IsDead()) and
				not inst:HasTag("playerghost") then
					inst.components.debuffable:AddDebuff("hornbuff", "hornbuff")
				end
			end)
		end
	end)

	local function ToggleState(inst)
		if inst:HasTag("charged") then
			inst:RemoveTag("charged")
			inst.components.inventoryitem.atlasname = "images/inventoryimages.xml"
			inst.components.inventoryitem:ChangeImageName("horn")

			inst.components.trader:Enable()
		else
			inst:AddTag("charged")
			inst.components.inventoryitem.atlasname = "inventoryimages/horn_charged.xml"
			inst.components.inventoryitem:ChangeImageName("horn_charged")

			SpawnFuelFX(inst)
			inst.components.trader:Disable()
		end
	end

	local function OnPlayed(inst, musician)
		if inst:HasTag("charged") then
			_G.ShakeAllCameras(_G.CAMERASHAKE.FULL, 2, .03, 0.15, inst, 6)

			inst.components.epicscare:Scare(15)

			local x, y, z = inst.Transform:GetWorldPosition()
			_G.SpawnPrefab("statue_transition_2").Transform:SetPosition(x, y, z)

			inst:DoTaskInTime(0, ToggleState)

			inst:DoTaskInTime(0.25, function()
				_G.SpawnPrefab("statue_transition").entity:AddFollower():FollowSymbol(musician.GUID, "horn01", 150, -190, 0)
			end)

			if _G.TheWorld:HasTag("cave") then
				_G.SpawnPrefab("cavein_debris").Transform:SetPosition(x, y, z)
				inst:DoTaskInTime(0.75, function()
					_G.TheWorld:PushEvent("ms_miniquake", { rad = 3, num = 5, duration = 1.5, target = inst })
				end)
			end
		end
	end

	inst.components.instrument:SetOnPlayedFn(OnPlayed)

	--------------------------------------------------------------------------

	inst:AddTag("gemsocket")

	local function ItemTradeTest(inst, item)
		if item.prefab == "nightmarefuel" then
			if inst:HasTag("charged") then
				return false, "DUPLICATE"
			end
			return true
		end
		return false, "NOTGEM"
	end

	inst:AddComponent("trader")
    inst.components.trader:SetAbleToAcceptTest(ItemTradeTest)
    inst.components.trader.onaccept = ToggleState

	--------------------------------------------------------------------------

	inst:AddComponent("epicscare")
    inst.components.epicscare:SetRange(15)

	local function OnSave(inst, data)
    	data.charged = inst:HasTag("charged")
	end

	local function OnLoad(inst, data)
    	if data ~= nil and data.charged then
			ToggleState(inst)
		end
	end

	inst.OnSave = OnSave
    inst.OnLoad = OnLoad
end)

AddPrefabPostInit("nightmarefuel", function(inst)
	if not inst.components.tradable then
		inst:AddComponent("tradable")
	end
end)
