--
-- PoettingerTerraDisc6000T
-- Specialization for PoettingerTerraDisc6000T
--
-- @author  	fruktor 
-- @version 	v0.1
-- @date  		22/02/11
-- @history:	v0.1 - Initial version
--

 
PoettingerTerraDisc6000T = {};

function PoettingerTerraDisc6000T.prerequisitesPresent(specializations)
	return true;
end;

function PoettingerTerraDisc6000T:load(xmlFile)
	self.expand = SpecializationUtil.callSpecializationsFunction("expand");
	
	--
	self.folding = {};
	self.folding.leftIdx = getXMLInt(xmlFile, "vehicle.folding#leftJointIdx"); 
	self.folding.rightIdx = getXMLInt(xmlFile, "vehicle.folding#rightJointIdx"); 
	self.folding.minRot = { Utils.degToRad(getXMLFloat(xmlFile, "vehicle.folding#minRot")) }; 
	self.folding.maxRot = { Utils.degToRad(getXMLFloat(xmlFile, "vehicle.folding#maxRot")) }; 
	self.folding.rotTime = getXMLFloat(xmlFile, "vehicle.folding#rotTime")*1000;
	self.setExpanded = true;
	self.isExpanded = true;
	self.isFolded = false;
	
	--
	self.street = {};
	self.street.jointIdx = getXMLInt(xmlFile, "vehicle.street#jointIdx"); 
	self.street.minRot = { Utils.degToRad(getXMLFloat(xmlFile, "vehicle.street#minRot")) }; 
	self.street.maxRot = { Utils.degToRad(getXMLFloat(xmlFile, "vehicle.street#maxRot")) }; 
	self.street.rotTime = getXMLFloat(xmlFile, "vehicle.street#rotTime")*1000;	
	self.frameSetDown = false;
	self.frameIsDown = false;
	self.frameIsUp = true;
	
	--
	self.hydraulics = {};
	self.updateHydraulics = false;
	local i=0;
	while true do
		local girl = Utils.indexToObject( self.components, getXMLString(xmlFile, string.format("vehicle.hydraulics.cylinder(%d)#girl",i)) );
		if girl == nil then
			break;
		end;
		local boy = Utils.indexToObject( self.components, getXMLString(xmlFile, string.format("vehicle.hydraulics.cylinder(%d)#boy",i)) );
		local ref = Utils.indexToObject( self.components, getXMLString(xmlFile, string.format("vehicle.hydraulics.cylinder(%d)#ref",i)) );
		local target = Utils.indexToObject( self.components, getXMLString(xmlFile, string.format("vehicle.hydraulics.cylinder(%d)#target",i)) );
		
		local entry = {};
		entry.girl = girl;
		entry.boy = boy;
		entry.ref = ref;
		entry.target = target;
		local x1, y1, z1 = getWorldTranslation(boy);
		local x2, y2, z2 = getWorldTranslation(ref);
		entry.length2 = Utils.vector3Length(x1-x2, y1-y2, z1-z2);
		
		i=i+1;
		table.insert(self.hydraulics, entry);
	end;	
	
	self.doJointOrientation = false;
	self.attacherJointCopy = nil;
	
	local cylinderedHydraulicSound = getXMLString(xmlFile, "vehicle.cylinderedHydraulicSound#file");
	if cylinderedHydraulicSound ~= nil and cylinderedHydraulicSound ~= "" then
		cylinderedHydraulicSound = Utils.getFilename(cylinderedHydraulicSound, self.baseDirectory);
		self.cylinderedHydraulicSound = createSample("cylinderedHydraulicSound");
		self.cylinderedHydraulicSoundEnabled = false;
		loadSample(self.cylinderedHydraulicSound, cylinderedHydraulicSound, false);
		self.cylinderedHydraulicSoundPitch = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cylinderedHydraulicSound#pitchOffset"), 1);
		self.cylinderedHydraulicSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cylinderedHydraulicSound#volume"), 1);
		setSamplePitch(self.cylinderedHydraulicSound, self.cylinderedHydraulicSoundPitch);
	else
		self.cylinderedHydraulicSoundPitch = 1;
		self.cylinderedHydraulicSoundVolume = 1;
	end;	
	
	--
	self.rotatingParts = {};
	i=0;
	while true do 
		local node = Utils.indexToObject( self.components, getXMLString(xmlFile, string.format("vehicle.rotatingParts.part(%d)#index",i)) );
		if node == nil then 
			break; 
		end;
		local radius = getXMLFloat(xmlFile, string.format("vehicle.rotatingParts.part(%d)#radius", i ) );
		local axis = getXMLInt(xmlFile, string.format("vehicle.rotatingParts.part(%d)#axis", i ) );
		local dir = getXMLFloat(xmlFile, string.format("vehicle.rotatingParts.part(%d)#dir", i ) );
		local entry = {};
		entry.node = node;
		entry.radius = radius;
		entry.rotationSpeedScale = 1.0 / ( 3.14159 * radius);
		entry.axis = axis;		
		entry.dir = dir;	
		table.insert(self.rotatingParts, entry);
		i=i+1;
	end;
	
	--
	self.feet = {};
	self.feet.jointIdx = getXMLInt(xmlFile, "vehicle.feet#jointIdx" );
	self.feet.node = Utils.indexToObject( self.components, getXMLString(xmlFile, "vehicle.feet#node") );
	self.feet.up = { getXMLFloat(xmlFile, "vehicle.feet#up" ) };
	self.feet.down = { getXMLFloat(xmlFile, "vehicle.feet#down" ) };
	self.feet.duration = getXMLFloat(xmlFile, "vehicle.feet#duration" )*1000;
	self.feet.setUp = false;
	self.feet.isUp = false;
	self.feet.isDown = false;
	
end

function PoettingerTerraDisc6000T:delete()
	if self.cylinderedHydraulicSound ~= nil then
		delete(self.cylinderedHydraulicSound);
    end;
 end;

function PoettingerTerraDisc6000T:readStream(streamId, connection)
	local lz = streamReadFloat32(streamId);
	local rz = streamReadFloat32(streamId);
	local sx = streamReadFloat32(streamId);
	
	local x,y,z = getRotation(self.componentJoints[self.folding.leftIdx].jointNode)
	setRotation(self.componentJoints[self.folding.leftIdx].jointNode, x, y, lz);
	setJointFrame(self.componentJoints[self.folding.leftIdx].jointIndex, 1, self.componentJoints[self.folding.leftIdx].jointNode);	

	local x,y,z = getRotation(self.componentJoints[self.folding.rightIdx].jointNode)
	setRotation(self.componentJoints[self.folding.rightIdx].jointNode, x, y, rz);
	setJointFrame(self.componentJoints[self.folding.rightIdx].jointIndex, 1, self.componentJoints[self.folding.rightIdx].jointNode);	

	local x,y,z = getRotation(self.componentJoints[self.street.jointIdx].jointNode)
	setRotation(self.componentJoints[self.street.jointIdx].jointNode, sx, y, z);
	setJointFrame(self.componentJoints[self.street.jointIdx].jointIndex, 1, self.componentJoints[self.street.jointIdx].jointNode);	
	
	local setExpanded = streamReadBool(streamId);
	local isExpanded = streamReadBool(streamId);
	local frameSetDown = streamReadBool(streamId);
	local frameIsDown = streamReadBool(streamId);
	self.setExpanded = setExpanded;
	self.isExpanded = isExpanded;
	self.frameSetDown = frameSetDown;
	self.frameIsDown = frameIsDown;
end;

function PoettingerTerraDisc6000T:writeStream(streamId, connection)
	local lx, ly, lz = getRotation(self.componentJoints[self.folding.leftIdx].jointNode);
	local rx, ry, rz = getRotation(self.componentJoints[self.folding.rightIdx].jointNode);
	local sx, sy, sz = getRotation(self.componentJoints[self.street.jointIdx].jointNode);
	streamWriteFloat32(streamId, lz);
	streamWriteFloat32(streamId, rz);
	streamWriteFloat32(streamId, sx);
	streamWriteBool(streamId, self.setExpanded);
	streamWriteBool(streamId, self.isExpanded);
	streamWriteBool(streamId, self.frameSetDown);
	streamWriteBool(streamId, self.frameIsDown);
end;

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

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

function PoettingerTerraDisc6000T:update(dt)
	if self:getIsActiveForInput() then
		if self.frameIsDown == true then
			if InputBinding.hasEvent(InputBinding.SYNKRO_EXPAND) then
				self:expand(not self.setExpanded);
	        end;
		end;
    end;
end;

function PoettingerTerraDisc6000T:updateTick(dt)

	--if self.isServer then
		if self.doJointOrientation == true and self.attacherVehicle ~= nil then
			for k,v in pairs(self.attacherVehicle.attachedImplements) do
				if v.object == self then
					local joint = self.attacherVehicle.attacherJoints[v.jointDescIndex];
					self.attacherJointCopy = joint;	
					--self.frameSetDown = not joint.moveDown;
					
					_=[[ self.allowsJointLimitMovementBackUp = joint.allowsJointRotLimitMovement;
					joint.allowsJointRotLimitMovement = false;
					setJointRotationLimit(joint.jointIndex, 2, true, math.rad(-180), math.rad(180));
					
					joint.minRotLimit[3] = math.rad(180);
					joint.maxRotLimit[3] = math.rad(180);
					self.doJointOrientation = false; ]]
				end;
			end;
		end;
	--end;
	
	if self:getIsActive() then
		self.wasToFast = false;	

		if self.attacherVehicle ~= nil and self.attacherJointCopy ~= nil then
			--setJointRotationLimit(self.attacherJointCopy.jointIndex, 2, true, math.rad(-180), math.rad(180));
			self.frameSetDown = not self.attacherJointCopy.moveDown;
		else
			self.frameSetDown = false;
		end;	
		
		
		--folding of 'arms'
		if (self.setExpanded == true and self.isExpanded == false) or
			(self.setExpanded == false and self.isFolded == false) then 
			
			local delta = 0.0001;
			
			self.updateHydraulics = true;
			self.isFolded = false;
			self.isExpanded = false;
			
			local tmp = not self.setExpanded;
			local x,y,z = getRotation(self.componentJoints[self.folding.rightIdx].jointNode);	
			local newRot = Utils.getMovedLimitedValues({z}, self.folding.minRot, self.folding.maxRot, 1, self.folding.rotTime, dt, tmp);

			setRotation(self.componentJoints[self.folding.leftIdx].jointNode, x, y, -newRot[1]);
			setJointFrame(self.componentJoints[self.folding.leftIdx].jointIndex, 1, self.componentJoints[self.folding.leftIdx].jointNode);

			setRotation(self.componentJoints[self.folding.rightIdx].jointNode, x, y, newRot[1]);
			setJointFrame(self.componentJoints[self.folding.rightIdx].jointIndex, 1, self.componentJoints[self.folding.rightIdx].jointNode);		
			
			if self.setExpanded == true and z < self.folding.minRot[1] + delta then
				self.isExpanded = true;
				self.updateHydraulics = false;
			end;
			if self.setExpanded == false and z > self.folding.maxRot[1] - delta then
				self.isFolded = true;
				self.updateHydraulics = false;
			end;
						
		end;
		
		--street-folding

		if (self.frameSetDown == true and self.frameIsDown == false) or
			(self.frameSetDown == false and self.frameIsUp == false) then
		
			--[[
			if self.frameSetDown == true then
				for i=3,4 do
					local wheel = self.wheels[i];
					setWheelShapeProps(wheel.node, wheel.wheelShape, 0, 10, wheel.steeringAngle);
				end;
			end;	
			]]--			

			local delta = 0.0001;
			
			self.updateHydraulics = true;
			self.frameIsDown = false;
			self.frameIsUp = false;
			
			local tmp = self.frameSetDown;
			local x,y,z = getRotation(self.componentJoints[self.street.jointIdx].jointNode);	
			local newRot = Utils.getMovedLimitedValues({x}, self.street.minRot, self.street.maxRot, 1, self.street.rotTime, dt, tmp);

			setRotation(self.componentJoints[self.street.jointIdx].jointNode, newRot[1], y, z);
			setJointFrame(self.componentJoints[self.street.jointIdx].jointIndex, 1, self.componentJoints[self.street.jointIdx].jointNode);

			--print("x="..x.." self.street.minRot="..self.street.minRot[1].." self.street.maxRot="..self.street.maxRot[1]);
			local eps = 0.0001;
			
			if self.frameSetDown == true and math.abs( x - self.street.maxRot[1] ) < eps then --- delta then
				self.frameIsDown = true;
				self.updateHydraulics = false;
			end;
			if self.frameSetDown == false and math.abs( x - self.street.minRot[1] ) < eps then -- delta then
				self.frameIsUp = true;
				self.updateHydraulics = false;
			end;
			
		end;
		
		if self:getIsActiveForSound() then

			if (self.frameIsDown == false and self.frameIsUp == false) or
				(self.isFolded == false and self.isExpanded == false) then
				
				if not self.cylinderedHydraulicSoundEnabled then
					playSample(self.cylinderedHydraulicSound, 0, self.cylinderedHydraulicSoundVolume, 0);
					self.cylinderedHydraulicSoundEnabled = true;
				end;
			else
				if self.cylinderedHydraulicSoundEnabled then
					stopSample(self.cylinderedHydraulicSound);
					self.cylinderedHydraulicSoundEnabled = false;
				end;			
			end;
		else
			if self.cylinderedHydraulicSoundEnabled then
				stopSample(self.cylinderedHydraulicSound);
				self.cylinderedHydraulicSoundEnabled = false;
			end;			
		end;
		
		--update hydraulics --------------------------------------------------
		for i, cylinder in pairs(self.hydraulics) do
		
			local ax, ay, az = getWorldTranslation(cylinder.girl);
			local bx, by, bz = getWorldTranslation(cylinder.target);
			local x, y, z = worldDirectionToLocal(getParent(cylinder.girl), bx-ax, by-ay, bz-az);
			
			local upX, upY, upZ = 0,1,0;
			if math.abs(y) > 0.99*Utils.vector3Length(x, y, z) then
				-- direction and up is parallel
				upY = 0;
				if y > 0 then
					upZ = 1;
				else
					upZ = -1;
				end;
			end;
			
			setDirection(cylinder.girl, x, y, z, upX, upY, upZ);
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(cylinder.boy, 0, 0, distance - cylinder.length2);			
		end;
		
		--rotatingParts -------------------------------------------------------
		--if self.frameIsUp == true and self.isExpanded == true then
		local x,y,z = getWorldTranslation(self.groundReferenceNode);
		local height = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
		if self.isExpanded == true and (height + self.groundReferenceThreshold) >= y  then
			if self.lastSpeedReal > 0.0001 then
				for i, part in pairs(self.rotatingParts) do
					local x,y,z = getRotation(part.node);
					if part.axis == 0 then
						x = x + self.movingDirection*(part.rotationSpeedScale * ((0.5*math.random()+0.5)*self.lastSpeedReal) * part.dir * dt);
					elseif part.axis == 1 then
						y = y + self.movingDirection*(part.rotationSpeedScale * ((0.5*math.random()+0.5)*self.lastSpeedReal) * part.dir * dt);
					elseif part.axis == 2 then
						z = z + self.movingDirection*(part.rotationSpeedScale * ((0.5*math.random()+0.5)*self.lastSpeedReal) * part.dir * dt);
					end;
					setRotation(part.node, x, y, z);
				end;
			end;
		end;
	else
		if self.cylinderedHydraulicSoundEnabled then
			stopSample(self.cylinderedHydraulicSound);
			self.cylinderedHydraulicSoundEnabled = false;
		end;		
	end;
	
	
	if (self.feet.setUp == true and self.feet.isUp == false) or 
		(self.feet.setUp == false and self.feet.isDown == false) then
	
		local delta = 0.0001;
	
		self.feet.isUp = false;
		self.feet.isDown = false;
	
		local tmp = not self.feet.setUp;
		local x,y,z = getTranslation(self.componentJoints[self.feet.jointIdx].jointNode);	
		local newVal = Utils.getMovedLimitedValues({z}, self.feet.down, self.feet.up, 1, self.feet.duration, dt, tmp);

		--setTranslation(self.feet.node, x, newVal[1], z);
		setTranslation(self.componentJoints[self.feet.jointIdx].jointNode, x, y, newVal[1]);
		setJointFrame(self.componentJoints[self.feet.jointIdx].jointIndex, 1, self.componentJoints[self.feet.jointIdx].jointNode);
		--print("newVal="..newVal[1].." setUp="..tostring(self.feet.setUp));
		if self.feet.setUp == true and newVal[1] < (self.feet.down[1] + delta) then
			self.feet.isUp = true;
		end;
		if self.feet.setUp == false and newVal[1] > (self.feet.up[1] - delta) then
			self.feet.isDown = true;
		end;
	end;
	
	if self.isServer and self.frameIsUp == false then
		for k,wheel in pairs(self.wheels) do
			if k>2 and k<5 then 
				setWheelShapeProps(wheel.node, wheel.wheelShape, 0, 3, 0);
			end;
		end;
	end;
		
end;

function PoettingerTerraDisc6000T:onAttach(attacherVehicle)
	self.doJointOrientation = true;
	setJointRotationLimit(self.componentJoints[2].jointIndex, 1, true, math.rad(-85), math.rad(85));
	self.feet.setUp = true;
end;

function PoettingerTerraDisc6000T:onDetach()
	self.doJointOrientation = false;
	setJointRotationLimit(self.componentJoints[2].jointIndex, 1, true, math.rad(0), math.rad(0));
	self.feet.setUp = false;

	--print("self.attacherJointCopy.allowsJointRotLimitMovement="..tostring(self.attacherJointCopy.allowsJointRotLimitMovement));
	if self.attacherJointCopy ~= nil then
		self.attacherJointCopy.allowsJointRotLimitMovement = self.allowsJointLimitMovementBackUp;	
		self.attacherJointCopy = nil;
	end;
end;

function PoettingerTerraDisc6000T:draw()
	if self.frameIsDown then
		if self.setExpanded then
			g_currentMission:addHelpButtonText(g_i18n:getText("SynkroT_CollapseFrame"), InputBinding.IMPLEMENT_EXTRA2);
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("SynkroT_ExpandFrame"), InputBinding.IMPLEMENT_EXTRA2);
		end;
	end;
end;

function PoettingerTerraDisc6000T:expand(setExpanded, noEventSend)
	ExpandEvent.sendEvent(self, setExpanded, noEventSend);
	self.setExpanded = setExpanded;
end;

function PoettingerTerraDisc6000T:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		local lz = Utils.getNoNil(getXMLFloat(xmlFile,key.."#lz"),1);
		local rz = Utils.getNoNil(getXMLFloat(xmlFile,key.."#rz"),1);
		local sx = Utils.getNoNil(getXMLFloat(xmlFile,key.."#sx"),1);
		
		local x,y,z = getRotation(self.componentJoints[self.folding.leftIdx].jointNode)
		setRotation(self.componentJoints[self.folding.leftIdx].jointNode, x, y, lz);
		setJointFrame(self.componentJoints[self.folding.leftIdx].jointIndex, 1, self.componentJoints[self.folding.leftIdx].jointNode);	

		local x,y,z = getRotation(self.componentJoints[self.folding.rightIdx].jointNode)
		setRotation(self.componentJoints[self.folding.rightIdx].jointNode, x, y, rz);
		setJointFrame(self.componentJoints[self.folding.rightIdx].jointIndex, 1, self.componentJoints[self.folding.rightIdx].jointNode);	

		local x,y,z = getRotation(self.componentJoints[self.street.jointIdx].jointNode)
		setRotation(self.componentJoints[self.street.jointIdx].jointNode, sx, y, z);
		setJointFrame(self.componentJoints[self.street.jointIdx].jointIndex, 1, self.componentJoints[self.street.jointIdx].jointNode);	
		
		local setExpanded = Utils.getNoNil(getXMLBool(xmlFile,key.."#setExpanded"), false);
		local isExpanded = Utils.getNoNil(getXMLBool(xmlFile,key.."#isExpanded"), false);
		local frameSetDown = Utils.getNoNil(getXMLBool(xmlFile,key.."#frameSetDown"), false);
		local frameIsDown = Utils.getNoNil(getXMLBool(xmlFile,key.."#frameIsDown"), false);
		self.setExpanded = setExpanded;
		self.isExpanded = isExpanded;
		self.frameSetDown = frameSetDown;
		self.frameIsDown = frameIsDown;
	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function PoettingerTerraDisc6000T:getSaveAttributesAndNodes(nodeIdent)
	local lx, ly, lz = getRotation(self.componentJoints[self.folding.leftIdx].jointNode);
	local rx, ry, rz = getRotation(self.componentJoints[self.folding.rightIdx].jointNode);
	local sx, sy, sz = getRotation(self.componentJoints[self.street.jointIdx].jointNode);
    local attributes = ' lz="'..tostring(lz)..'"'..
		' rz="'..tostring(rz)..'"'..
		' sx="'..tostring(sx)..'"'..
		' setExpanded="'..tostring(setExpanded)..'"'..
		' isExpanded="'..tostring(isExpanded)..'"'..
		' frameSetDown="'..tostring(frameSetDown)..'"'..
		' frameIsDown="'..tostring(frameIsDown)..'"';
    local node = nil;
    return attributes, node;

end;