
TOOL.Category		= "Wire - Physics"
TOOL.Name			= "Simple Servo"
TOOL.Command		= nil
TOOL.ConfigName		= nil

TOOL.ClientConVar[ "model" ] 		= "models/props_vehicles/carparts_wheel01a.mdl"
TOOL.ClientConVar[ "rotate" ]       = 1

// Add Default Language translation (saves adding it to the txt files)
if ( CLIENT ) then
	language.Add( "Tool_wire_simple_servo_name", "Simple Servo Tool (wire)" )
    language.Add( "Tool_wire_simple_servo_desc", "Attaches a servo to something." )
    language.Add( "Tool_wire_simple_servo_0", "Primary: Attach a servo. Secondary: Change the model" )
	
	language.Add( "undone_WireSimpleServo", "Undone Wire Servo" )
	language.Add( "Cleanup_wire_simple_servos", "Wired Servos" )
	language.Add( "Cleaned_wire_simple_servos", "Cleaned up all Wired Simple Servos" )
	language.Add( "sbox_maxwire_simple_servos", "You've reached the wired servos limit!" )

end

if (SERVER) then
    CreateConVar('sbox_maxwire_simple_servos', 30)
end 

cleanup.Register( "wire_simple_servos" )

/*---------------------------------------------------------
   Places a wheel
---------------------------------------------------------*/
function TOOL:LeftClick( trace )

	if ( trace.Entity && trace.Entity:IsPlayer() ) then return false end
	
	// If there's no physics object then we can't constraint it!
	if ( SERVER && !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then return false end
	
	if (CLIENT) then return true end
	
	local ply = self:GetOwner()

	if ( !self:GetSWEP():CheckLimit( "wire_simple_servos" ) ) then return false end

	local targetPhys = trace.Entity:GetPhysicsObjectNum( trace.PhysicsBone )
	
	// Get client's CVars
	local model			= self:GetClientInfo( "model" )
	
	if ( !util.IsValidModel( model ) ) then return false end
	if ( !util.IsValidProp( model ) ) then return false end	
	
	local Ang = trace.HitNormal:Angle()
	if(self:GetClientInfo("rotate")) then
		Ang.pitch = Ang.pitch+90
		//Ang.r = Ang.r+90
	end
	
	// Create the wheel
	local servoEnt = MakeWireServo( ply, trace.HitPos, Ang, model )
			
	local CurPos = servoEnt:GetPos()
	local NearestPoint = servoEnt:NearestPoint( CurPos - (trace.HitNormal * 512) )
	local servoOffset = CurPos - NearestPoint
		
	servoEnt:SetPos( trace.HitPos + servoOffset + trace.HitNormal )
	
	// Wake up the physics object so that the entity updates
	servoEnt:GetPhysicsObject():Wake()
	
	local TargetPos = servoEnt:GetPos()
			
	// Set the hinge Axis perpendicular to the trace hit surface
	local LPos1 = servoEnt:GetPhysicsObject():WorldToLocal( TargetPos + trace.HitNormal )
	local LPos2 = targetPhys:WorldToLocal( trace.HitPos )
	
	local constraint, axis = constraint.Axis( servoEnt, trace.Entity, 0, trace.PhysicsBone, LPos1,	LPos2, friction, 0, nocollide, false, ply )
	
	undo.Create("WireSimpleServo")
	undo.AddEntity( axis )
	undo.AddEntity( constraint )
	undo.AddEntity( servoEnt )
	undo.SetPlayer( ply )
	undo.Finish()
	
	ply:AddCleanup( "wire_servos", axis )
	ply:AddCleanup( "wire_servos", constraint )
	ply:AddCleanup( "wire_servos", servoEnt )

	return true

end


/*---------------------------------------------------------
   Apply new values to the wheel
---------------------------------------------------------*/
function TOOL:RightClick( trace )
	if CLIENT and trace.Entity:IsValid() then return true end
	if not trace.Entity:IsValid() then return end
	local model = trace.Entity:GetModel()
	self:GetOwner():ConCommand("wire_simple_servo_model "..model);
	self.Model = model
	return true;
end

function TOOL:Reload(trace)
	local rotate = self:GetClientInfo("rotate");
	rotate = rotate + 1
	rotate = rotate % 2
	Msg("Rotate: "..rotate);
	self:GetOwner():ConCommand("wire_simple_servo_rotate "..rotate);
	return true;
end

if ( SERVER ) then

	/*---------------------------------------------------------
	   For duplicator, creates the wheel.
	---------------------------------------------------------*/
	function MakeWireServo( pl, Pos, Ang, Model )
		
		if ( !pl:CheckLimit( "wire_servos" ) ) then return false end
		
		local servo = ents.Create( "gmod_wire_simple_servo" )
		if ( !servo:IsValid() ) then return end
		
		servo:SetModel( Model )
		servo:SetPos( Pos )
		servo:SetAngles( Ang )
		servo:Spawn()
		
		servo:SetPlayer( pl )	
	
		servo.model = model

		pl:AddCount( "wire_simple_servos", servo )
		
		return servo
		
	end

	duplicator.RegisterEntityClass( "gmod_wire_simple_servo", MakeWireServo, "Pos", "Ang", "model", "Vel", "aVel", "frozen" )
	
	
end

function TOOL:UpdateGhostWireServo( ent, player )

	if ( !ent ) then return end
	if ( !ent:IsValid() ) then return end
	
	local tr 	= utilx.GetPlayerTrace( player, player:GetCursorAimVector() )
	local trace 	= util.TraceLine( tr )
	if (!trace.Hit) then return end
	
	if ( trace.Entity:IsPlayer() ) then
	
		ent:SetNoDraw( true )
		return
		
	end
	
	local Ang = trace.HitNormal:Angle()
	if(self:GetClientInfo("rotate")) then
		Ang.pitch = Ang.pitch+90
		//Ang.r = Ang.r+90
	end
	local CurPos = ent:GetPos()
	local NearestPoint = ent:NearestPoint( CurPos - (trace.HitNormal * 512) )
	local servoOffset = CurPos - NearestPoint
	
	local min = ent:OBBMins()
	ent:SetPos( trace.HitPos + trace.HitNormal + servoOffset )
	ent:SetAngles( Ang )
	
	ent:SetNoDraw( false )
	
end

/*---------------------------------------------------------
   Maintains the ghost wheel
---------------------------------------------------------*/
function TOOL:Think()

	if (!self.GhostEntity || !self.GhostEntity:IsValid() || self.GhostEntity:GetModel() != self:GetClientInfo( "model" )) then
		self:MakeGhostEntity( self:GetClientInfo( "model" ), Vector(0,0,0), Angle(0,0,0) )
	end
	
	self:UpdateGhostWireServo( self.GhostEntity, self:GetOwner() )
	
end
