AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

------------------------------//
-- Spawn
function ENT:SpawnFunction(ply, tr)
	if (not tr.Hit) then return end
	local SpawnPos = tr.HitPos + tr.HitNormal * 1
	local ent = ents.Create(self.ClassName)
	local angle = ply:GetAimVector():Angle()
	angle = Angle(0, angle.yaw, 0)
	ent:SetAngles(angle)
	ent:SetPos(SpawnPos)
	ent:Spawn()
	ent:Activate()
	zrmine.f.SetOwnerID(ent, ply)

	return ent
end

function ENT:Initialize()
	self:SetModel(self.Model)
	self:PhysicsInit(SOLID_VPHYSICS)
	self:SetMoveType(MOVETYPE_VPHYSICS)
	self:SetSolid(SOLID_VPHYSICS)
	self:SetUseType(SIMPLE_USE)
	local phys = self:GetPhysicsObject()

	if (phys:IsValid()) then
		phys:Wake()
		phys:EnableMotion(false)
	end

	self:UseClientSideAnimation()
	self:Spawn_Filling()
	self:Spawn_MoltenMetal()
	self:Spawn_Bars()
	self:Spawn_Coals()
	self:Spawn_Lava()

	timer.Simple(1, function()
		if (IsValid(self)) then
			self:Empty_Melter()
		end
	end)
end

function ENT:Spawn_Filling()
	self.ResourceFilling = ents.Create("zrms_gravelanim")
	self.ResourceFilling:SetAngles(self:GetAngles())
	self.ResourceFilling:SetPos(self:GetPos() + self:GetUp() * -2)
	self.ResourceFilling:Spawn()
	self.ResourceFilling:Activate()
	self.ResourceFilling:SetModel("models/Zerochain/props_mining/zrms_melter_filling.mdl")
	self.ResourceFilling:SetParent(self, self:LookupAttachment("body"))
	self.ResourceFilling:SetNoDraw(true)
end

function ENT:Spawn_MoltenMetal()
	self.MoltenMetal = ents.Create("zrms_gravelanim")
	self.MoltenMetal:SetAngles(self:GetAngles())
	self.MoltenMetal:SetPos(self:GetAttachment(self:LookupAttachment("moltenmetal")).Pos + self:GetForward() * 1.5 + self:GetUp() * -2)
	self.MoltenMetal:Spawn()
	self.MoltenMetal:Activate()
	self.MoltenMetal:SetModel("models/Zerochain/props_mining/zrms_melter_moltenmetal.mdl")
	self.MoltenMetal:SetParent(self, self:LookupAttachment("moltenmetal"))
	self.MoltenMetal:SetNoDraw(true)
end

function ENT:Spawn_Bars()
	self.Bars = ents.Create("zrms_gravelanim")
	self.Bars:SetAngles(self:GetAngles())
	self.Bars:SetPos(self:GetAttachment(self:LookupAttachment("moltenmetal")).Pos + self:GetForward() * 1 + self:GetUp() * -2)
	self.Bars:Spawn()
	self.Bars:Activate()
	self.Bars:SetModel("models/Zerochain/props_mining/zrms_melter_bars.mdl")
	self.Bars:SetParent(self, self:LookupAttachment("moltenmetal"))
	self.Bars:SetNoDraw(true)
end

function ENT:Spawn_Coals()
	self.Coals = ents.Create("zrms_gravelanim")
	self.Coals:SetAngles(self:GetAngles())
	self.Coals:SetPos(self:GetPos() + self:GetUp() * -23)
	self.Coals:Spawn()
	self.Coals:Activate()
	self.Coals:SetModel("models/Zerochain/props_mining/zrms_melter_coal.mdl")
	self.Coals:SetParent(self)
	self.Coals:SetNoDraw(true)
end

function ENT:Spawn_Lava()
	self.Lava = ents.Create("zrms_gravelanim")
	local ang = self:GetAngles()
	ang:RotateAroundAxis(self:GetUp(), -90)
	self.Lava:SetAngles(ang)
	self.Lava:SetPos(self:GetPos())
	self.Lava:Spawn()
	self.Lava:Activate()
	self.Lava:SetModel("models/Zerochain/props_mining/zrms_melter_lava.mdl")
	self.Lava:SetParent(self)
	self.Lava:SetNoDraw(true)
end

--Coal
function ENT:Add_Coal(coal)
	if (self:GetCoalAmount() < zrmine.config.Melter_Coal_Capacity) then
		self:SetCoalAmount(self:GetCoalAmount() + coal:GetResourceAmount())
		self:Update_Coal()
		zrmine.f.CreateEffectTable("zrms_melter_coalfill", "zrmine_sfx_addgravel", self, self:GetAngles(), self:GetPos() + self:GetUp() * 25 + self:GetForward() * 70)

		if (zrmine.config.ResourceCrates_ReUse) then
			coal:Empty_Basket()
			--coal:SetPos(self:GetPos() + self:GetUp()*30 + self:GetForward()*60)
		else
			coal:Remove()
			zrmine.f.CreateEffectTable(nil, "zrmine_sfx_crate_break", self, self:GetAngles(), self:GetPos())
		end
	end

	self:Melting_Check()
end

function ENT:Remove_Coal(coal)
	if (self:GetCoalAmount() > 0) then
		self:SetCoalAmount(self:GetCoalAmount() - coal)
	end

	self:Update_Coal()
end

function ENT:Update_Coal()
	self.CoalFill_Height = (20 / zrmine.config.Melter_Coal_Capacity) * self:GetCoalAmount()
	self.Coals:SetNoDraw(false)

	if (self.CoalFill_Height > 20) then
		self.CoalFill_Height = 20
	end

	if (self.CoalFill_Height < 0 or self:GetCoalAmount() <= 0) then
		self.CoalFill_Height = 0
		self.Coals:SetNoDraw(true)
	end

	self.Coals:SetPos(self:GetPos() + self:GetUp() * -23)
	self.Coals:SetPos(self.Coals:GetPos() + self.Coals:GetUp() * self.CoalFill_Height)
end

-- Logic
function ENT:Empty_Melter()
	self:SetCurrentState("WAITING_FOR_ORDER")
	self:CreateAnim_Table("open", 1)
	self:SetResourceType("Empty")
	self:SetResourceAmount(0)
	self.ResourceFilling:SetNoDraw(true)
	self.Bars:SetNoDraw(true)
	self.MoltenMetal:SetNoDraw(true)
	self.Lava:SetNoDraw(true)
end

function ENT:Add_Resource(crate, ply)
	if (self:GetCurrentState() ~= "WAITING_FOR_ORDER") then return end
	local rType = crate:GetResourceType()
	local rAmount = crate:GetResourceAmount()

	if (self:GetResourceType() == "Empty" or self:GetResourceType() == rType) then
		if (self:GetResourceAmount() < zrmine.config.Melter_Vars[rType].OreAmount) then
			self:SetResourceType(rType)
			local needAmount = zrmine.config.Melter_Vars[rType].OreAmount - self:GetResourceAmount()

			if (needAmount >= rAmount) then
				if (zrmine.config.ResourceCrates_ReUse) then
					crate:Empty_Basket()
					crate:SetPos(self:GetPos() + self:GetUp() * 75)
					zrmine.f.CreateEffectTable(nil, "zrmine_sfx_addgravel", self, self:GetAngles(), self:GetPos(), nil)
				else
					crate:Remove()
					zrmine.f.CreateEffectTable(nil, "zrmine_sfx_crate_break", self, self:GetAngles(), self:GetPos(), nil)
				end

				self:SetResourceAmount(self:GetResourceAmount() + rAmount)
			else
				zrmine.f.CreateEffectTable(nil, "zrmine_sfx_addgravel", self, self:GetAngles(), self:GetPos(), nil)
				self:SetResourceAmount(self:GetResourceAmount() + needAmount)
				crate:Decrease_Resource(needAmount, rType)
				crate:SetPos(self:GetPos() + self:GetUp() * 75)
			end

			self.ResrcFill_Height = (25 / zrmine.config.Melter_Vars[rType].OreAmount) * self:GetResourceAmount()

			if (self.ResrcFill_Height > 25) then
				self.ResrcFill_Height = 25
			end

			self.ResourceFilling:SetNoDraw(false)
			self.ResourceFilling:SetPos(self:GetPos() + self:GetUp() * self.ResrcFill_Height)
		end

		if (self:GetResourceAmount() >= zrmine.config.Melter_Vars[rType].OreAmount) then
			self:SetCurrentState("CHAMBER_FULL")
			zrmine.f.Notify(ply, zrmine.language.Melter_Full, 1)
		end
	end

	self:UpdateVisuals()
	self:Melting_Check()
end

function ENT:Collect_Resource(crate, ply)
	local InvAmount = self:GetResourceAmount()
	local FillAmount

	if (self:GetCurrentState() == "WAITING_FOR_ORDER" or self:GetCurrentState() == "CHAMBER_FULL" and InvAmount > 0) then
		if (InvAmount > zrmine.config.ResourceCrates_Capacity) then
			FillAmount = zrmine.config.ResourceCrates_Capacity
		else
			FillAmount = InvAmount
		end

		crate:Add_Resource(FillAmount, self:GetResourceType())
		self:SetResourceAmount(InvAmount - FillAmount)
		zrmine.f.CreateEffectTable(nil, "zrmine_sfx_addgravel", self, self:GetAngles(), self:GetPos(), nil)

		if (self:GetResourceAmount() <= 0) then
			self:SetCurrentState("WAITING_FOR_ORDER")
			self:SetResourceType("Empty")
			self:SetResourceAmount(0)
			self.ResourceFilling:SetNoDraw(true)
		end
	end
end

function ENT:UpdateVisuals()
	if (self:GetResourceType() == "Dirt") then
		self.ResourceFilling:SetSkin(0)
	elseif (self:GetResourceType() == "Iron") then
		self.ResourceFilling:SetSkin(1)
	elseif (self:GetResourceType() == "Bronze") then
		self.ResourceFilling:SetSkin(2)
	elseif (self:GetResourceType() == "Silver") then
		self.ResourceFilling:SetSkin(3)
	elseif (self:GetResourceType() == "Gold") then
		self.ResourceFilling:SetSkin(4)
	end
end

function ENT:Start_Melting()
	zrmine.f.CreateEffectTable(nil, "zrmine_sfx_melter_move", self, self:GetAngles(), self:GetPos(), nil)
	self:SetCurrentState("MELTING")
	self:CreateAnim_Table("close", 1)

	timer.Simple(2, function()
		if (IsValid(self)) then
			zrmine.f.CreateEffectTable("zrms_melter_coalpit", nil, self, self:GetAngles(), self:GetPos(), self:LookupAttachment("coalpit"))
			zrmine.f.CreateEffectTable("zrms_melter_head", nil, self, self:GetAngles(), self:GetPos(), self:LookupAttachment("body"))
			zrmine.f.CreateEffectTable("zrms_melter_chimney", nil, self, self:GetAngles(), self:GetPos(), self:LookupAttachment("chimney01"))
			zrmine.f.CreateEffectTable("zrms_melter_chimney", nil, self, self:GetAngles(), self:GetPos(), self:LookupAttachment("chimney02"))
			self:SetIsLowered(true)
			self.ResourceFilling:SetNoDraw(true)
		end
	end)

	timer.Simple(2, function()
		if (IsValid(self)) then
			self:Remove_Coal(zrmine.config.Melter_Vars[self:GetResourceType()].CoalAmount)
		end
	end)

	timer.Simple(zrmine.config.Melter_Vars[self:GetResourceType()].MeltDuration + 3, function()
		if (IsValid(self)) then
			self:Unloading()
		end
	end)
end

function ENT:Unloading()
	zrmine.f.CreateEffectTable(nil, "zrmine_sfx_melter_move", self, self:GetAngles(), self:GetPos(), nil)
	self:EmitSound("doors/door_metal_rusty_move1.wav", 75, 100, 1, CHAN_AUTO)
	self:SetCurrentState("UNLOADING")
	zrmine.f.RemoveEffectNamed(self, "zrms_melter_coalpit")
	self:CreateAnim_Table("unload_start", 1)
	self:SetIsLowered(false)

	timer.Simple(2, function()
		if (IsValid(self)) then
			zrmine.f.CreateEffectTable("zrms_melter_unload", nil, self, self:GetAngles(), self:GetPos(), self:LookupAttachment("effectpoint01"))
			self.MoltenMetal:SetNoDraw(false)
			self.Lava:SetNoDraw(false)
			zrmine.f.CreateAnimTable(self.Lava, "fill", 5)
			local speed = (1 / zrmine.config.Melter_UnloadTime) * 2
			self:EmitSound("doors/door_metal_rusty_move1.wav", 75, 100, 1, CHAN_AUTO)
			zrmine.f.CreateAnimTable(self.MoltenMetal, "fill", speed)
		end
	end)

	timer.Simple(zrmine.config.Melter_UnloadTime, function()
		if (IsValid(self)) then
			self.Lava:SetNoDraw(true)
			self:EmitSound("doors/door_metal_rusty_move1.wav", 75, 100, 1, CHAN_AUTO)
			self:CreateAnim_Table("unload_stop", 1)
			self:CoolingBars()
			zrmine.f.RemoveEffectNamed(self, "zrms_melter_unload")
			zrmine.f.RemoveEffectNamed(self, "zrms_melter_chimney")
			zrmine.f.RemoveEffectNamed(self, "zrms_melter_head")
		end
	end)
end

function ENT:CoolingBars()
	local rType = self:GetResourceType()

	timer.Simple(zrmine.config.Melter_Vars[rType].CoolingTime, function()
		if (IsValid(self)) then
			self:EmitSound("doors/door_metal_rusty_move1.wav", 75, 100, 1, CHAN_AUTO)
			zrmine.f.CreateEffectTable(nil, "zrmine_sfx_melter_move", self, self:GetAngles(), self:GetPos())
			self:CreateAnim_Table("unload_bars", 1)
			zrmine.f.CreateAnimTable(self.MoltenMetal, "idle", 1)
			local btype = self:GetResourceType()

			if (btype == "Iron") then
				self.Bars:SetSkin(0)
			elseif (btype == "Bronze") then
				self.Bars:SetSkin(1)
			elseif (btype == "Silver") then
				self.Bars:SetSkin(2)
			elseif (btype == "Gold") then
				self.Bars:SetSkin(3)
			end

			self.Bars:SetNoDraw(false)
		end
	end)

	timer.Simple(zrmine.config.Melter_Vars[rType].CoolingTime + 1.75, function()
		if (IsValid(self)) then
			self.Bars:SetNoDraw(true)
			self.MoltenMetal:SetNoDraw(true)
			self:Unloading_Bars(self:GetResourceType())

			--Vrondakis
			if (LevelSystemConfiguration or manolis) then
				local ply = zrmine.f.GetOwner(self)

				if IsValid(ply) then
					ply:addXP(zrmine.config.Vrondakis["Melting"].XP, " ", true)
				end
			end
		end
	end)

	timer.Simple(zrmine.config.Melter_Vars[rType].CoolingTime + 4, function()
		if (IsValid(self)) then
			self:Empty_Melter()
		end
	end)
end

function ENT:Unloading_Bars(btype)
	local delay = 0

	for i = 1, 6 do
		timer.Simple(delay, function()
			local ent = ents.Create("zrms_bar")
			local ang = self:GetAngles()
			ang:RotateAroundAxis(self:GetRight(), -60)
			ent:SetAngles(ang)
			ent:SetPos(self:GetPos() + self:GetUp() * 45 + self:GetForward() * -55 + self:GetRight() * -22 + self:GetRight() * (6 * i))
			ent:Spawn()
			ent:Activate()
			self:DeleteOnRemove(ent)
			ent:SetMetalType(btype)
			ent:UpdateVisuals()
		end)

		delay = delay + 0.05
	end
end

function ENT:Melting_Check()
	local rType = self:GetResourceType()

	if (rType ~= "Empty" and self:GetResourceAmount() >= zrmine.config.Melter_Vars[rType].OreAmount and self:GetCoalAmount() >= zrmine.config.Melter_Vars[rType].CoalAmount and self:GetCurrentState() ~= "MELTING" and self:GetCurrentState() ~= "UNLOADING") then
		self:Start_Melting()
	end
end

-- Damage Stuff
function ENT:OnTakeDamage(dmg)
	self:TakePhysicsDamage(dmg)
	local damage = dmg:GetDamage()
	local entHealth = zrmine.config.Damageable["Melter"].EntityHealth

	if (entHealth > 0) then
		self.CurrentHealth = (self.CurrentHealth or entHealth) - damage

		if (self.CurrentHealth <= 0) then
			self:Destruct()
			self:Remove()
		end
	end
end

function ENT:Destruct()
	local vPoint = self:GetPos()
	local effectdata = EffectData()
	effectdata:SetStart(vPoint)
	effectdata:SetOrigin(vPoint)
	effectdata:SetScale(1)
	util.Effect("Explosion", effectdata)
end

-- Animation
function ENT:CreateAnim_Table(anim, speed)
	if (self:LookupSequence(anim) == self:GetSequence()) then return end
	zrmine.f.CreateAnimTable(self, anim, speed)
end
