/*
	Stargate SENT for GarrysMod10
	Copyright (C) 2007  aVoN

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
--################# HEADER #################

-- Reload handler
-- Someone just entered lua_reloadents into console. Therefore, remove all stargates in the map or they will get all fucked
if(CurTime() > 10) then StarGate.CallReload(_,true) end;

--Include
AddCSLuaFile("cl_init.lua");
AddCSLuaFile("shared.lua");

include("shared.lua");
include("modules/lib.lua");
include("modules/events.lua");

-- Defines
ENT.CDSIgnore = true; -- CDS Immunity
function ENT:gcbt_breakactions() end; ENT.hasdamagecase = true; -- GCombat invulnarability!

-- Offsets for "InRamp"-Spawning
ENT.RampOffset = {
	["models/zup/ramps/sgc_ramp.mdl"] = Vector(0,0,0),
	["models/zup/ramps/brick_01.mdl"] = Vector(0,0,-10),
}

--################# SENT CODE #################
--################# Initialize
function ENT:Initialize()
	--################# Config
	self.DHDRange = StarGate.CFG:Get("dhd","range",1000); -- Maximum range a DHD can be in before the gate says "Hey, you do not belong to me, get the fuck out"
	--################# General defines and inits
	self:RegisterSequenceTable(); -- Register a "Copy" of the self.Sequence table, so out sequence won't be mixed between Atlantis/SG1 gates
	self.GatePrivat = self.GatePrivat or false; -- Is the gate Private?
	self.GateName = self.GateName or ""; -- The name of this gate
	self.GateAddress = self.GateAddress or ""; -- Our Address
	self.DialledAddress = {}; -- Still used for compatibility reasons
	self.IsOpen = false; -- Still used for compatibility reasons
	self.Dialling = false; -- Still used for compatibility reasons
	self.DialType = {};
	self.Entity:SetUseType(SIMPLE_USE);
	--################# Wire!
	self:CreateWireInputs("Dial Address","Dial Mode","Close","Disable Autoclose");
	self:CreateWireOutputs("Active","Open","Inbound","Chevron");
	--################# Fix for Duplicator, or the ring and chevron will look strange when loading a saved gate
	local ang = self.Entity:GetAngles();
	if(ang ~= Angle(0,0,0)) then
		self.Entity:SetAngles(Angle(0,0,0));
		local e = self.Entity;
		timer.Simple(0,
			function()
				if(ang and ValidEntity(e)) then
					e:SetAngles(ang);
				end
			end
		);
	end
	--################# Set physic and entity properties
	local phys = self.Entity:GetPhysicsObject();
	if(phys:IsValid()) then
		phys:EnableMotion(false);
		phys:SetMass(32000); -- A stargate weights 32 tons!
	end
end

--################# For the spawnfunction, to put a gate directly into ramps @aVoN
function ENT:PutIntoRamps(t)
	local e = t.Entity;
	if(not ValidEntity(e)) then return end;
	local mdl = e:GetModel();
	if(self.RampOffset[mdl]) then
		-- Check, if there is already a gate snapped to it...
		for _,v in pairs(StarGate.GetConstrainedEnts(e,2) or {}) do
			if(ValidEntity(v) and v:GetClass():find("stargate_")) then return end;
		end
		-- Freeze ramp
		local phys = e:GetPhysicsObject();
		if(phys:IsValid()) then
			phys:EnableMotion(false);
		end
		self.Entity:SetAngles(e:GetAngles());
		self.Entity:SetPos(e:LocalToWorld(self.RampOffset[mdl]));
		constraint.Weld(self.Entity,e,0,0,0,true);
		e.CDSIgnore = true; -- Fixes Combat Damage System destroying Ramps - http://mantis.39051.vs.webtropia.com/view.php?id=45
		return e;
	end
end

--#################  When getting removed..
function ENT:OnRemove()
	self:Close(); -- Close the horizon
	self:StopActions(); -- Stop all actions and sounds
	self:DHDDisable(0); -- Shutdown near DHD's
	if(ValidEntity(self.Target)) then
		if(self.IsOpen) then
			self.Target:DeactivateStargate(true);
		elseif(self.Dialling) then
			self.Target:EmergencyShutdown(true);
		end
	end
end

--################# When it get's hurt, make it flicker etc
-- FIXME: Write new damage system
function ENT:OnTakeDamage(d)
end

--#################  Use - Open the Dial Menu @aVoN
function ENT:Use(p)
	if(ValidEntity(p) and p:IsPlayer()) then
		if(hook.Call("StarGate.Player.CanDialGate",GAMEMODE,p,self.Entity) == false) then return end; -- Not allowed to dial!
		local dialog = "StarGate.OpenDialMenu";
		if(hook.Call("StarGate.Player.CanModifyGate",GAMEMODE,p,self.Entity) == false) then
			dialog = "StarGate.OpenDialMenuDHD"; -- He is not allowed to modify stuff, so show him the normal dialling dialoge!
		elseif(self.GateSpawnerProtected) then -- It's a protected gate. Can this user change it?
			local allowed = hook.Call("StarGate.Player.CanModifyProtectedGate",GAMEMODE,p,self.Entity);
			if(allowed == nil) then allowed = (p:IsAdmin() or SinglePlayer()) end;
			if(not allowed) then
				dialog = "StarGate.OpenDialMenuDHD";
			end
		end
		umsg.Start(dialog,p);
		umsg.Entity(self.Entity);
		umsg.End();
		self.LastUse = time;
	end
end


--##################################
--#### Wire Inputs
--##################################


--################# Wire input @aVoN
function ENT:TriggerInput(k,v)
	if(k == "Dial Address") then
		local char = string.char(v):upper();
		if(v == 13 and #self.DialledAddress == 8) then -- Enter Key
			local fast = self:GetWire("Dial Mode",0) >= 1;
			if(self.Entity:GetClass() == "stargate_atlantis") then fast = true end; -- SGA is ALWAYS dialling fast! - FIXME: Add new dialling to this gate (with the new sounds!)
			self:SetDialMode(false,fast); -- If DialMode is 0, we dial slowly, if Dial Mode is greater we dial fast
			self:StartDialling();
		elseif(v == 127) then -- Backspace key
			table.remove(self.DialledAddress);
		elseif(char:find("[A-Z0-9@]")) then -- Only alphanumerical and the @
			if(#self.DialledAddress < 6 and not table.HasValue(self.DialledAddress,char)) then
				table.insert(self.DialledAddress,char);
			end
			if(#self.DialledAddress == 6) then
				table.insert(self.DialledAddress,"#");
				table.insert(self.DialledAddress,"DIAL");
			end
		end
	elseif(k == "Close") then
		self:AbortDialling();
	end
end

--################# Wire ouput - Relay to a mobile DHD @aVoN
function ENT:WireOutput(k,v)
	for _,e in pairs(ents.FindByClass("mobile_dhd")) do
		if((e:GetPos()-self.Entity:GetPos()):Length() <= self.DHDRange) then
			e:SetWire(k,v);
		end
	end
end
