Cat345B = {}

function Cat345B.prerequisitesPresent(specializations)
     Vehicle.registerJointType("frontloader");
    return SpecializationUtil.hasSpecialization(Steerable, specializations);
end;

function Cat345B:load(xmlFile)
local jointDesc = {};

   local shovelAttacher = {};
	local jointTypeStr = getXMLString(xmlFile,"vehicle.attacherJoints.attacherJoint#jointType");
	shovelAttacher.joint = getXMLString(xmlFile,"vehicle.attacherJoints.attacherJoint#index");
	shovelAttacher.index = 0;
	self.shovel = shovelAttacher;
	if jointTypeStr ~= nil then
		local jointType = Vehicle.jointTypeNameToInt[jointTypeStr];

		if jointType == nil then
      		Vehicle.registerJointType(jointTypeStr);
			print("register Jointtype: " .. jointTypeStr);
			jointType = Vehicle.jointTypeNameToInt[jointTypeStr];
		end;

		if jointType ~= nil then
			self.attacherJoints[1].jointType = jointType;
		end;
	end;
    
    local workingArmNode = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.workingArm#index"));
	if workingArmNode ~= nil then
        self.workingArm = {};
        self.workingArm.node = workingArmNode;
        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.workingArm#minRot"));
        self.workingArm.minRot = {};
        self.workingArm.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.workingArm.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.workingArm.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.workingArm#maxRot"));
        self.workingArm.maxRot = {};
        self.workingArm.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.workingArm.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.workingArm.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));
		
		self.workingArm.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.workingArm#rotTime"), 2)*1000;
		self.workingArm.fixPoint = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.workingArm#fixPoint"));
    end;
	

    local transformer1Node = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.transformer#index"));
    if transformer1Node ~= nil then
        self.transformer = {};
        self.transformer.node = transformer1Node;
        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.transformer#minRot"));
        self.transformer.minRot = {};
        self.transformer.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.transformer.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.transformer.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.transformer#maxRot"));
        self.transformer.maxRot = {};
        self.transformer.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.transformer.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.transformer.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));
		
		self.transformer.rotTime = self.workingArm.rotTime;
		self.transformer.fixPoint = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.transformer#fixPoint"));
		self.transformer.transform2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.transformer#index2"));
    end;
	
	
	local rotationPartNodetourelle = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.tourelle#index"));
	if rotationPartNodetourelle ~= nil then
        self.tourelle = {};
        self.tourelle.node = rotationPartNodetourelle;
        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.tourelle#minRot"));
        self.tourelle.minRot = {};
        self.tourelle.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.tourelle.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.tourelle.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.tourelle#maxRot"));
        self.tourelle.maxRot = {};
        self.tourelle.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.tourelle.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.tourelle.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.tourelle.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.tourelle#rotTime"), 2)*1000;
        self.tourelle.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.tourelle#touchRotLimit"), 10))
    end;
  
    
    local rotationPartNodebras2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bras2#index"));
    if rotationPartNodebras2 ~= nil then
        self.bras2 = {};
        self.bras2.node = rotationPartNodebras2;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.bras2#minRot"));
        self.bras2.minRot = {};
        self.bras2.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.bras2.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.bras2.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.bras2#maxRot"));
        self.bras2.maxRot = {};
        self.bras2.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.bras2.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.bras2.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.bras2.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.bras2#rotTime"), 2)*1000;
        self.bras2.pivotverin = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bras2#pivotverin"));
    end;
    
	
	local rotationPartNodeworkingArm2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.workingArm2#index"));
    if rotationPartNodeworkingArm2 ~= nil then
        self.workingArm2 = {};
        self.workingArm2.node = rotationPartNodeworkingArm2;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.workingArm2#minRot"));
        self.workingArm2.minRot = {};
        self.workingArm2.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.workingArm2.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.workingArm2.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.workingArm2#maxRot"));
        self.workingArm2.maxRot = {};
        self.workingArm2.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.workingArm2.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.workingArm2.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.workingArm2.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.workingArm2#rotTime"), 2)*1000;
		self.workingArm2.pivotverin = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.workingArm2#pivotverin"));
    end;
	
	
    local rotationPartNodebras1 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bras1#index"));
    if rotationPartNodebras1 ~= nil then
        self.bras1 = {};
        self.bras1.node = rotationPartNodebras1;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.bras1#minRot"));
        self.bras1.minRot = {};
        self.bras1.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.bras1.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.bras1.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.bras1#maxRot"));
        self.bras1.maxRot = {};
        self.bras1.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.bras1.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.bras1.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.bras1.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.bras1#rotTime"), 2)*1000;
	    self.bras1.pivotverin = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bras1#pivotverin"));
    end;
       
	
		self.verin2 = {};
		self.verin2.node = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin2#indexverin"));
		self.verin2.tige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin2#indextige"));
		self.verin2.translationtige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin2#translationtige"));
		local ax, ay, az = getWorldTranslation(self.verin2.tige);
		local bx, by, bz = getWorldTranslation(self.verin2.translationtige);
		self.verin2.tigeDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
    
		self.verin1 = {};
		self.verin1.node = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin1#indexverin"));
		self.verin1.tige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin1#indextige"));
		self.verin1.translationtige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.verin1#translationtige"));
		local ax, ay, az = getWorldTranslation(self.verin1.tige);
		local bx, by, bz = getWorldTranslation(self.verin1.translationtige);
		self.verin1.tigeDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
    
    
		self.hydraulicMainArm = {};
		self.hydraulicMainArm.node = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.hydraulicMainArm#indexHydraulic"));
		self.hydraulicMainArm.punch = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.hydraulicMainArm#indexPunch"));
		self.hydraulicMainArm.translationPunch = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.hydraulicMainArm#translationPunch"));
		local ax, ay, az = getWorldTranslation(self.hydraulicMainArm.punch);
		local bx, by, bz = getWorldTranslation(self.hydraulicMainArm.translationPunch);
		self.hydraulicMainArm.punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
    
    
		self.bielle1 = {};
		self.bielle1.node = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bielle1#indexverin"));
		self.bielle1.tige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bielle1#indextige"));
		self.bielle1.translationtige = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.bielle1#translationtige"));
		local ax, ay, az = getWorldTranslation(self.bielle1.tige);
		local bx, by, bz = getWorldTranslation(self.bielle1.translationtige);
		self.bielle1.tigeDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
    
        
		local objectAttacher = {};
		objectAttacher.joint = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.anchor#index"));
		objectAttacher.index = 0;
		self.object = objectAttacher;
		self.attachedObject = nil;
		self.objectAttachable = false;
		self.objectInRange = nil;


	hydraulicSoundFile = Utils.getFilename("sound/hydraulicUp.wav", self.baseDirectory);
    self.hydraulicSoundId = createSample("hydraulicSound");
    loadSample(self.hydraulicSoundId, hydraulicSoundFile, false);
    self.hydraulicPlaying = false;
	self.hydraulicSoundAllow = false;

end;

function Cat345B:delete()
end;

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

function Cat345B:keyEvent(unicode, sym, modifier, isDown)    

	if sym == Input.KEY_KP_7 then
		self.rotationMinbras2 = isDown;            
	end;
	
	if sym == Input.KEY_KP_4 then
		self.rotationMaxbras2 = isDown;
	end;
	
	if sym == Input.KEY_KP_8 then
		self.rotationMinbras1 = isDown;	 
	end;
	
	if sym == Input.KEY_KP_5 then
		self.rotationMaxbras1 = isDown;
	end;
	
	if sym == Input.KEY_KP_3 then
		self.rotationMintourelle = isDown;
	end;
	
	if sym == Input.KEY_KP_1 then
		self.rotationMaxtourelle = isDown;
	end;
	
	if sym == Input.KEY_KP_6 then
		self.rotationMaxworkingArm = isDown;
	end;
	
	if sym == Input.KEY_KP_9 then
		self.rotationMinworkingArm = isDown;
	end;
	
	if sym == Input.KEY_KP_9 then
		self.rotationMaxworkingArm2 = isDown;
        end;
	if sym == Input.KEY_KP_6 then
		self.rotationMinworkingArm2 = isDown;
	end;

	
	if isDown then
		if sym == Input.KEY_KP_1 or sym == Input.KEY_KP_3 or sym == Input.KEY_KP_4
		or sym == Input.KEY_KP_5 or sym == Input.KEY_KP_6 or sym == Input.KEY_KP_7 or sym == Input.KEY_KP_8
		or sym == Input.KEY_KP_9 then
			self.hydraulicSoundAllow = true;
		end;
	else
		self.hydraulicSoundAllow = false;
	end;
	
end;

function Cat345B:update(dt)


	local doRotate = self.rotationMaxtourelle or self.rotationMintourelle
    if self.tourelle ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.tourelle.node);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.tourelle.maxRot, self.tourelle.minRot, 3, self.tourelle.rotTime, dt, not self.rotationMaxtourelle);
		setRotation(self.tourelle.node, unpack(newRot));
	if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
	end;
	end;
   
	
   	local doRotate = self.rotationMaxbras2 or self.rotationMinbras2
    if self.bras2 ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.bras2.node);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.bras2.maxRot, self.bras2.minRot, 3, self.bras2.rotTime, dt, not self.rotationMaxbras2);
		setRotation(self.bras2.node, unpack(newRot));
		if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
		end;
	
	elseif not self.hydraulicSoundAllow and self.hydraulicPlaying then
		stopSample(self.hydraulicSoundId);
		self.hydraulicPlaying = false;
	end;
	
	
   	local doRotate = self.rotationMaxbras1 or self.rotationMinbras1
    if self.bras1 ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.bras1.node);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.bras1.maxRot, self.bras1.minRot, 3, self.bras1.rotTime, dt, not self.rotationMaxbras1);
		setRotation(self.bras1.node, unpack(newRot));
		if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
	end;
	
	elseif not self.hydraulicSoundAllow and self.hydraulicPlaying then
		stopSample(self.hydraulicSoundId);
		self.hydraulicPlaying = false;
	end;
	
    local doRotate = self.rotationMaxworkingArm or self.rotationMinworkingArm
	if self.workingArm ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.workingArm.node);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.workingArm.maxRot, self.workingArm.minRot, 3, self.workingArm.rotTime, dt, self.rotationMaxworkingArm);
		setRotation(self.workingArm.node, unpack(newRot));
		if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
	end;
	
	elseif not self.hydraulicSoundAllow and self.hydraulicPlaying then
		stopSample(self.hydraulicSoundId);
		self.hydraulicPlaying = false;
	end;
	
	local doRotate = self.rotationMaxworkingArm or self.rotationMinworkingArm
	if self.transformer ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.transformer.node);
	    local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.transformer.maxRot, self.transformer.minRot, 3, self.transformer.rotTime, dt, self.rotationMaxworkingArm);
		setRotation(self.transformer.node, unpack(newRot));
		if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
	end;
	
	elseif not self.hydraulicSoundAllow and self.hydraulicPlaying then
		stopSample(self.hydraulicSoundId);
		self.hydraulicPlaying = false;
	end;
	local doRotate = self.rotationMaxworkingArm2 or self.rotationMinworkingArm2
    if self.workingArm2 ~= nil and doRotate and self.hydraulicSoundAllow then
		local x, y, z = getRotation(self.workingArm2.node);
		local rot = {x,y,z};
		local newRot = Utils.getMovedLimitedValues(rot, self.workingArm2.maxRot, self.workingArm2.minRot, 3, self.workingArm2.rotTime, dt, not self.rotationMaxworkingArm2);
		setRotation(self.workingArm2.node, unpack(newRot));
		if self.hydraulicSoundAllow and not self.hydraulicPlaying then
			playSample(self.hydraulicSoundId,0,1,0);
			self.hydraulicPlaying = true;
	end;
	
	elseif not self.hydraulicSoundAllow and self.hydraulicPlaying then
		stopSample(self.hydraulicSoundId);
		self.hydraulicPlaying = false;
	end;
		
    if self.hydraulicMainArm ~= nil and self.transformer ~= nil then
		local ax, ay, az = getWorldTranslation(self.hydraulicMainArm.node);
		local bx, by, bz = getWorldTranslation(self.transformer.fixPoint);
		local x, y, z = worldDirectionToLocal(getParent(self.hydraulicMainArm.node), bx-ax, by-ay, bz-az);
		setDirection(self.hydraulicMainArm.node, x*-1, y*-1, z*-1, 0, 1, 0);
		if self.hydraulicMainArm.punch ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
		    setTranslation(self.hydraulicMainArm.punch, 0, 0, (distance-self.hydraulicMainArm.punchDistance)*-1);
		end;
	end;

	if self.transformer ~= nil and self.workingArm ~= nil then
	    local ax, ay, az = getWorldTranslation(self.transformer.transform2);
	    local bx, by, bz = getWorldTranslation(self.workingArm.fixPoint);
	    local x, y, z = worldDirectionToLocal(getParent(self.transformer.transform2), bx-ax, by-ay, bz-az);
	    setDirection(self.transformer.transform2, x*-1, y*-1, z*-1, 0, 1, 0);
	end;

    
	if self.verin2 ~= nil and self.bras2 ~= nil then
		local ax, ay, az = getWorldTranslation(self.verin2.node);
		local bx, by, bz = getWorldTranslation(self.bras2.pivotverin);
		local x, y, z = worldDirectionToLocal(getParent(self.verin2.node), bx-ax, by-ay, bz-az);
		setDirection(self.verin2.node, x*-1, y*-1, z*-1, 0, 1, 0);
		if self.verin2.tige ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(self.verin2.tige, 0, 0, (distance-self.verin2.tigeDistance)*-1);
		end;
	end;
	if self.verin1 ~= nil and self.bras1 ~= nil then
		local ax, ay, az = getWorldTranslation(self.verin1.node);
		local bx, by, bz = getWorldTranslation(self.bras1.pivotverin);
		local x, y, z = worldDirectionToLocal(getParent(self.verin1.node), bx-ax, by-ay, bz-az);
		setDirection(self.verin1.node, x*-1, y*-1, z*-1, 0, 1, 0);
		if self.verin1.tige ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(self.verin1.tige, 0, 0, (distance-self.verin1.tigeDistance)*-1);
		end;
	end;
	if self.bielle1 ~= nil and self.workingArm2 ~= nil then
		local ax, ay, az = getWorldTranslation(self.bielle1.node);
		local bx, by, bz = getWorldTranslation(self.workingArm2.pivotverin);
		local x, y, z = worldDirectionToLocal(getParent(self.bielle1.node), bx-ax, by-ay, bz-az);
		setDirection(self.bielle1.node, x*-1, y*-1, z*-1, 0, 1, 0);
		if self.bielle1.tige ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(self.bielle1.tige, 0, 0, (distance-self.bielle1.tigeDistance)*-1);
		end;
	end;
end;

function Cat345B:connectCollisions(varName)
	local Collision = self.collisionArm[varName];
	local constr = JointConstructor:new();
	constr:setActors(self.rootNode, Collision.collision);
	constr:setJointTransforms(Collision.armAttacher, Collision.collisionAttacher);
	for i=1, 3 do
		constr:setRotationLimit(i-1, 0, 0, 0);
		constr:setTranslationLimit(i-1, true, 0, 0);
	end;
	Collision.index = constr:finalize();
end;


function Cat345B:validateAttacherJoint(implement, jointDesc, dt)
    return true;
end;

function Cat345B:draw()
end;

function Cat345B:validateAttacherJoint(implement, jointDesc, dt)
    return true;
end;