--
-- Traktor250
-- Specialization for Traktor250
--
-- @author  	Manuel Leithner
-- @version 	v2.0
-- @date  		15/10/10
-- @history:	v1.0 - Initial version
--				v2.0 - added network support, changed update to updateTick
--

Traktor250 = {};

function Traktor250.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(ArticulatedSteering, specializations);
end;

function Traktor250:load(xmlFile)

	-- Defines attributes of backHydraulic
	self.backHydraulic = {};
	self.backHydraulic.rootArm = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.backHydraulic#rootArm"));
	
	self.backAttacherJoint = {};
	self.backAttacherJoint.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.trailerAttacherJoints#node"));
	self.backAttacherJoint.lowRot = Utils.degToRad(getXMLFloat(xmlFile, "vehicle.trailerAttacherJoints#lowRot"));
	self.backAttacherJoint.upRot = Utils.degToRad(getXMLFloat(xmlFile, "vehicle.trailerAttacherJoints#upRot"));
	
	self.implementAdapter = {};
	self.implementAdapter.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherJoints#adapter"));
	self.implementAdapter.attacherJoint = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherJoints#attacherJoint"));
	self.implementAdapter.topReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherJoints#topReferenceNode"));
	self.implementAdapter.backup = {};
	local x,y,z = getTranslation(self.implementAdapter.node);
	self.implementAdapter.backup.trans = {x,y,z};
	self.implementAdapter.backup.attacherJoint = nil;
    self.implementAdapter.backup.topReferenceNode = nil;	
	
	local shaftCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.drivingPowerShafts#count"), 0);
    self.drivingPowerShafts = {};
    for i=1, shaftCount do
		local shaft = {};
        local shaftName = string.format("vehicle.drivingPowerShafts.powerShaft%d", i);
		shaft.node = Utils.indexToObject(self.components, getXMLString(xmlFile, shaftName .. "#index"));		
		shaft.trans = Utils.getNoNil(getXMLFloat(xmlFile, shaftName .. "#translation"), 0);
		local x,y,z = getTranslation(getParent(shaft.node));
		shaft.orgTrans = {x,y,z};
		shaft.rot = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, shaftName .. "#rotation"), 0));	
		shaft.speedFactor = Utils.getNoNil(getXMLFloat(xmlFile, shaftName .. "#speedFactor"), 2);
		table.insert(self.drivingPowerShafts, shaft);        
    end;

    
	
	self.topArm = {};
	self.topArm.node = getChildAt(self.attacherJoints[1].topArm.rotationNode, 0);
	self.topArm.rotation = {getRotation(self.topArm.node)};
	
	self.minAutoRotateSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheels#minAutoRotateBackSpeed"), self.autoRotateBackSpeed);
	self.maxAutoRotateSpeed = self.autoRotateBackSpeed;
	self.maxSpeed = getXMLFloat(xmlFile, "vehicle.wheels#maxSpeed");
	
	self.updateJoint = false;
end;

function Traktor250:delete()
end;

function Traktor250:readStream(streamId, connection)
end;

function Traktor250:writeStream(streamId, connection)
end;

function Traktor250:mouseEvent(posX, posY, isDown, isUp, button)
end;

function Traktor250:keyEvent(unicode, sym, modifier, isDown)
end;

function Traktor250:update(dt)
	if self:getIsActive() then
		for _, part in pairs(self.movingParts) do
			part.isDirty = true;
		end;	
	end;
end;

function Traktor250:updateTick(dt)

	if self:getIsActive() then
	
		self.autoRotateBackSpeed = ((self.lastSpeed*3600 / self.maxSpeed) * (self.maxAutoRotateSpeed - self.minAutoRotateSpeed)) + self.minAutoRotateSpeed;
		
		for _, shaft in pairs(self.drivingPowerShafts) do
			local x,y,z = getRotation(self.wheels[1].driveNode);
			setRotation(shaft.node, 0 ,0, x*shaft.speedFactor);
			
			if shaft.trans ~= 0 then
				local newTrans = shaft.trans * self.articulatedSteering.curRot/self.articulatedSteering.maxRot;
				local x,y,z = unpack(shaft.orgTrans);
				setTranslation(getParent(shaft.node), x + newTrans,y,z);
			end;
			if shaft.rot ~= 0 then
				newRot = shaft.rot * self.articulatedSteering.curRot/self.articulatedSteering.maxRot;
				setRotation(getParent(shaft.node), 0, newRot, 0);
			end;
			
		end;

		
		if self.backHydraulic ~= nil then
			-- set correct rotation on rootArm			
			local x, y, z = getRotation(self.attacherJoints[1].bottomArm.rotationNode);
			setRotation(self.backHydraulic.rootArm, x, y, z);	
		end;		
	end;
end;

function Traktor250:draw()	
end;


function Traktor250:attachImplement(implement)
	
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;

	if jointType == Vehicle.JOINTTYPE_IMPLEMENT then
		if jointIndex == 1 then
			setRotation(self.topArm.node, 0, 0, 0);
			setVisibility(getParent(self.backAttacherJoint.node), false);
			
			local attacherJoint = implement.object.attacherJoint;
			unlink(self.implementAdapter.node);
			link(attacherJoint.node, self.implementAdapter.node);
			setTranslation(self.implementAdapter.node, 0, 0, 0);
			
			if attacherJoint.topReferenceNode ~= nil then
				local x,y,z = getWorldTranslation(attacherJoint.topReferenceNode);
				local x1,y1,z1 = getWorldTranslation(self.implementAdapter.node);
				local xDir, yDir, zDir = worldDirectionToLocal(getParent(self.implementAdapter.node), x-x1, y-y1, z-z1);
				setDirection(self.implementAdapter.node, xDir, yDir, zDir, 0,1,-1);
				
				local x,y,z = getRotation(self.implementAdapter.node);
				setRotation(self.implementAdapter.node, x, math.rad(90), 0);
			else
				setRotation(self.implementAdapter.node, math.rad(-90), math.rad(90), 0);
			end;
			
			self.implementAdapter.backup.attacherJoint = attacherJoint.node;
			self.implementAdapter.backup.topReferenceNode = attacherJoint.topReferenceNode;			
			attacherJoint.node = self.implementAdapter.attacherJoint;
			attacherJoint.topReferenceNode = self.implementAdapter.topReferenceNode;
		
			setVisibility(self.implementAdapter.node, true);
		end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILER then
		if jointIndex == 2 then
			setRotation(self.attacherJoints[1].bottomArm.rotationNode, self.backAttacherJoint.upRot, 0, 0);
			setRotation(self.backAttacherJoint.node, -self.backAttacherJoint.upRot, 0, 0);
		end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILERLOW then
		if jointIndex == 3 then	
			setRotation(self.attacherJoints[1].bottomArm.rotationNode, self.backAttacherJoint.lowRot, 0, 0);
			setRotation(self.backAttacherJoint.node, -self.backAttacherJoint.lowRot, 0, 0);
		end;
	end;
	self.updateJoint = true;	
end;

function Traktor250:detachImplement(implementIndex)

	local implement = self.attachedImplements[implementIndex];
	local jointIndex = implement.jointDescIndex;

	if jointIndex == 1 then
		local x,y,z = unpack(self.topArm.rotation);
		setRotation(self.topArm.node, x,y,z);
		setVisibility(getParent(self.backAttacherJoint.node), true);
		
		setVisibility(self.implementAdapter.node, false);
		local attacherJoint = implement.object.attacherJoint;
		
		attacherJoint.node = self.implementAdapter.backup.attacherJoint;
		attacherJoint.topReferenceNode = self.implementAdapter.backup.topReferenceNode;
		
		unlink(self.implementAdapter.node);
		link(self.components[2].node, self.implementAdapter.node);
		setTranslation(self.implementAdapter.node, unpack(self.implementAdapter.backup.trans));
		setRotation(self.implementAdapter.node, math.rad(-90), 0,0);
		
	elseif jointIndex == 2 or jointIndex == 3 then
		setRotation(self.attacherJoints[1].bottomArm.rotationNode, 0, 0, 0);
		setRotation(self.backAttacherJoint.node, 0, 0, 0);
	end;
end;

function Traktor250:validateAttacherJoint(implement, jointDesc, dt)
    if self.updateJoint then
        self.updateJoint = false;
        return true;
    end;
    return false;
end;

function Traktor250:onLeave()
	
end;

function Traktor250:onEnter()
	
end;