--
-- TaarupMower
--
-- @author  	Manuel Leithner (SFM-Modding)
-- @date  		11/10/10
--

TaarupMower = {};

function TaarupMower.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(TaarupMowerCut, specializations);
end;

function TaarupMower:load(xmlFile)

	self.getIsAreaActive = Utils.overwrittenFunction(self.getIsAreaActive, TaarupMower.getIsAreaActive);	
	self.setIsArmDown = SpecializationUtil.callSpecializationsFunction("setIsArmDown");
	self.setTransport = SpecializationUtil.callSpecializationsFunction("setTransport");
	
	
	self.mowerFoldingParts = {};
	local i = 0;
    while true do
        local partName = string.format("vehicle.mowerFoldingParts.part(%d)", i);
		local part = {};
        local joint = getXMLInt(xmlFile, partName .. ".mainPart#joint");
        if joint == nil then
            break;
        end;
		local mainPart = {};
		mainPart.joint = self.componentJoints[joint];
		mainPart.minRot = {};
		local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, partName .. ".mainPart#minRot"));
        mainPart.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        mainPart.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        mainPart.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));
		
		mainPart.maxRot = {};
		x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, partName .. ".mainPart#maxRot"));
        mainPart.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        mainPart.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        mainPart.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));
	
		mainPart.maxLimit = {};
		x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, partName .. ".mainPart#maxLimit"));
        mainPart.maxLimit[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        mainPart.maxLimit[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        mainPart.maxLimit[3] = Utils.degToRad(Utils.getNoNil(z, 0));
		mainPart.currentLimit = {0, 0, 0};
		mainPart.isDown = false;
		
		local mower = {};
		mower.joint = self.componentJoints[getXMLInt(xmlFile, partName .. ".mower#joint")];
		mower.maxLimit = {};
		x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, partName .. ".mower#maxLimit"));
        mower.maxLimit[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        mower.maxLimit[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        mower.maxLimit[3] = Utils.degToRad(Utils.getNoNil(z, 0));
		mower.cuttingArea = self.cuttingAreas[getXMLInt(xmlFile, partName .. ".mower#cuttingArea")];
		mower.currentLimit = {0, 0, 0};
		
		part.mower = mower;

		part.mainPart = mainPart;
		part.moveTime = Utils.getNoNil(getXMLFloat(xmlFile, partName .. "#moveTime"),2)*1000;
		part.workingTime = Utils.getNoNil(getXMLFloat(xmlFile, partName .. "#workingTime"),2)*1000;
		part.isDown = false;
		table.insert(self.mowerFoldingParts, part);		
        i = i+1;
	end;

	self.doTransportCheck = false;
	self.doChangesForTransport = false;
	self.isTransport = false;
	self.isReadyToTransport = true;
	self.isLoading = true;

	self.rotateSpinners = {};
	local i=0;
	while true do
		local baseName = string.format("vehicle.rotateSpinners.node(%d)", i);
		local index = getXMLString(xmlFile, baseName.. "#index");
		local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, baseName.. "#rotationSpeed"));
		local rotationSpeed = {x,y,z};
		local runOutTime = Utils.getNoNil(getXMLFloat(xmlFile, baseName.. "#runOutTime"), 2)*1000;
		if index == nil or rotationSpeed == nil or runOutTime == nil then
			break;
		end;
		local node = Utils.indexToObject(self.components, index);
		if node ~= nil then
			local entry = {};
			entry.node = node;
			entry.runOutTime = runOutTime;
			entry.rotationSpeedMax = rotationSpeed;
			entry.rotationSpeedMin = {0,0,0};
			entry.rotationSpeedCurrent = {0,0,0};
			table.insert(self.rotateSpinners, entry);
		end;
		i = i+1;
	end;	
	
	local rotarySound = getXMLString(xmlFile, "vehicle.rotarySound#file");
	if rotarySound ~= nil and rotarySound ~= "" then
		rotarySound = Utils.getFilename(rotarySound, self.baseDirectory);
		self.rotarySound = createSample("rotarySound");
		loadSample(self.rotarySound, rotarySound, false);
		self.rotarySoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.rotarySound#pitchOffset"), 0);
		self.rotarySoundVolume = 0.0;
		self.rotarySoundVolumeMin = 0.0;
		self.rotarySoundVolumeMax = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.rotarySound#volume"), 1.0);
		self.rotarySoundEnabled = false;
	end;
	

 	self.setVehicleRpmUp = SpecializationUtil.callSpecializationsFunction("setVehicleRpmUp");
	self.saveMinRpm = 0; 

end;

function TaarupMower:delete()
	if self.rotarySound ~= nil then
		delete(self.rotarySound);
	end;
end;

function TaarupMower:readStream(streamId, connection)
	self.isLoading = true;
	local isTransport = streamReadBool(streamId);
	self:setTransport(isTransport, true);
	for k, foldingPart in pairs(self.mowerFoldingParts) do
		local isDown = streamReadBool(streamId);
		self:setIsArmDown(isDown, k, true);
	end;
	
end;

function TaarupMower:writeStream(streamId, connection)
	streamWriteBool(streamId, self.isTransport);
	for k, foldingPart in pairs(self.mowerFoldingParts) do	
		streamWriteBool(streamId, foldingPart.mainPart.isDown);
	end;
	
end;

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

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

end;

function TaarupMower:update(dt)
    if self:getIsActive() then 
		if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
			if not self.isTransport then
				if InputBinding.hasEvent(InputBinding.TAARUP5090_LOWER_LEFT) then
					local foldingArm = self.mowerFoldingParts[2].mainPart;
					self:setIsArmDown(2, not foldingArm.isDown);
				end;
				if InputBinding.hasEvent(InputBinding.TAARUP5090_LOWER_RIGHT) then
					local foldingArm = self.mowerFoldingParts[1].mainPart;
					self:setIsArmDown(1, not foldingArm.isDown);
				end;
				if InputBinding.hasEvent(InputBinding.TAARUP5090_LOWER_ALL) then
					local isDown = self.mowerFoldingParts[1].mainPart.isDown or self.mowerFoldingParts[2].mainPart.isDown;
					for k, part in pairs(self.mowerFoldingParts) do
						self:setIsArmDown(k, not isDown);
					end;	
				end;		
			end;
		end;
	end;
	if self:getIsActiveForInput() and not self:hasInputConflictWithSelection() then	
		if self.isReadyToTransport then
			if InputBinding.hasEvent(InputBinding.TAARUP5090_TRANSPORT) then
				local isTransport = false;
				for k, part in pairs(self.mowerFoldingParts) do
					isTransport = part.isDown;
					break;
				end;	
				self:setTransport(isTransport);
			end;
		end;	
		if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) and self.PTOId then
			self.printWarningTime1 = self.time + 1500;
		end;	
		if not self.isTransport then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
				  self:setIsTurnedOn(not self.isTurnedOn);
			end;			
		end;	
	end;
end;

function TaarupMower:updateTick(dt)

	if self:getIsActive() then

		local isKeyEvent = false;	
		if self.isTurnedOn then
 			isKeyEvent = true;	
		else
 			isKeyEvent = false;	
		end;

		self:setVehicleRpmUp(dt, isKeyEvent);	
		local volume = Utils.getMovedLimitedValues({self.rotarySoundVolume}, {self.rotarySoundVolumeMax}, {self.rotarySoundVolumeMin}, 1, 1200, dt, not self.isTurnedOn);
		self.rotarySoundVolume = volume[1];
			if self.isTurnedOn and not self.PTOId then
				if not self.rotarySoundEnabled and self:getIsActiveForSound() then
					playSample(self.rotarySound, 0, self.rotarySoundVolume, 0);
					setSamplePitch(self.rotarySound, self.rotarySoundPitchOffset);
					self.rotarySoundEnabled = true;
				end;
				if self.rotarySoundVolume < self.rotarySoundVolumeMax then
					setSampleVolume(self.rotarySound, self.rotarySoundVolume);
				end;
				else
				if self.rotarySoundEnabled then
					if self.rotarySoundVolume <= self.rotarySoundVolumeMin then
						stopSample(self.rotarySound);
						self.rotarySoundEnabled = false;
					else
						setSampleVolume(self.rotarySound, self.rotarySoundVolume);
					end;
				end;
			end;	
			for k, spinner in pairs(self.rotateSpinners) do
				local values = Utils.getMovedLimitedValues(spinner.rotationSpeedCurrent, spinner.rotationSpeedMax, spinner.rotationSpeedMin, 3, spinner.runOutTime, dt, not self.isTurnedOn);
				spinner.rotationSpeedCurrent = values;
				rotate(spinner.node, unpack(spinner.rotationSpeedCurrent));
			end;

	
		self.isReadyToTransport = true;
		for _, part in pairs(self.mowerFoldingParts) do
			self.isReadyToTransport = self.isReadyToTransport and not part.mainPart.isDown;
		end;
		
		if self.attacherVehicle ~= nil then	
			for _, foldingPart in pairs(self.mowerFoldingParts) do
				local mainPart = foldingPart.mainPart;
				local x, y, z = getRotation(mainPart.joint.jointNode);
				local rot = {x,y,z};
				local newRot = Utils.getMovedLimitedValues(rot, mainPart.maxRot, mainPart.minRot, 3, foldingPart.moveTime, dt, not foldingPart.isDown);
				setRotation(mainPart.joint.jointNode, unpack(newRot));
				setJointFrame(mainPart.joint.jointIndex, 0, mainPart.joint.jointNode);

				local mower = foldingPart.mower;
				setJointFrame(mower.joint.jointIndex, 0, mower.joint.jointNode);

				local newArmLimit = Utils.getMovedLimitedValues(mainPart.currentLimit, mainPart.maxLimit, {0,0,0}, 3, foldingPart.workingTime, dt, not mainPart.isDown);
				local newmowerLimit = Utils.getMovedLimitedValues(mower.currentLimit, mower.maxLimit, {0,0,0}, 3, foldingPart.workingTime, dt, not mainPart.isDown);
				for i=1, 3 do
					setJointRotationLimit(mainPart.joint.jointIndex, i-1, true, -newArmLimit[i], newArmLimit[i]);
					setJointRotationLimit(mower.joint.jointIndex, i-1, true, -newmowerLimit[i], newmowerLimit[i]);
				end;
				mainPart.currentLimit = newArmLimit;
				mower.currentLimit = newmowerLimit;

				local isExpanded = true;
                for i=1, 3 do
					isExpanded = isExpanded and newmowerLimit[i] >= mower.maxLimit[i] * 0.5;
                end;	
				
				-- for _, part in pairs(self.movingParts) do
					-- part.isDirty = true;
				-- end;
			end;

		end;
		if self.isTurnedOn and self.movingDirection ~= 0 and self.lastAreaBiggerZero then
			local foldingArmRight = self.mowerFoldingParts[1].mainPart;
			local foldingArmLeft = self.mowerFoldingParts[2].mainPart;
			if foldingArmRight.isDown then
				Utils.setEmittingState(self.mowerParticleSystemsRight, true);
			else
				Utils.setEmittingState(self.mowerParticleSystemsRight, false);
			end;
			if foldingArmLeft.isDown then
				Utils.setEmittingState(self.mowerParticleSystemsLeft, true);
			else
				Utils.setEmittingState(self.mowerParticleSystemsLeft, false);
			end;
		else
			Utils.setEmittingState(self.mowerParticleSystemsRight, false);		
			Utils.setEmittingState(self.mowerParticleSystemsLeft, false);		
		end;
	end;
	
end;


function TaarupMower:draw()	
	if self:getIsActive() then
		local foldingArmRight = self.mowerFoldingParts[1].mainPart;
		local foldingArmLeft = self.mowerFoldingParts[2].mainPart;
		if foldingArmRight.isDown or foldingArmLeft.isDown then
			if self.wasToFast then
				g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getKeyNamesOfDigitalAction(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
			end;		
		end;
	end;
    if self.isTransport then
        g_currentMission:addHelpButtonText(string.format(g_i18n:getText("TAARUP5090_TRANSPORT_OFF"), self.typeDesc), InputBinding.TAARUP5090_TRANSPORT);
    else
		if self.isReadyToTransport then
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("TAARUP5090_TRANSPORT_ON"), self.typeDesc), InputBinding.TAARUP5090_TRANSPORT);
		end;
		g_currentMission:addExtraPrintText(string.format(g_i18n:getText("TAARUP5090_CONTROL"), self.typeDesc) .. " " .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.TAARUP5090_LOWER_ALL) .. "/" .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.TAARUP5090_LOWER_LEFT) .. "/" .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.TAARUP5090_LOWER_RIGHT));
    end;
end;

function TaarupMower:onAttach(attacherVehicle)
	self.attacherVehicle = attacherVehicle;
	if self.attacherVehicleCopy == nil then
		self.attacherVehicleCopy = self.attacherVehicle;
	end;
	self.saveMinRpm = self.attacherVehicle.motor.minRpm;
	-- self.isTransport = false;
	local isTransport = false;
	for k, part in pairs(self.mowerFoldingParts) do
		isTransport = part.isDown;
			break;
	end;	
	self:setTransport(false);	
end;

function TaarupMower:onDetach()
      if self.deactivateOnDetach then
          TaarupMower.onDeactivate(self);
      else
          TaarupMower.onDeactivateSounds(self)
      end;
	for k, steerable in pairs(g_currentMission.steerables) do
		if self.attacherVehicleCopy == steerable then
			steerable.motor.minRpm = self.saveMinRpm;
			self.attacherVehicleCopy = nil;
		end;
	end;
	-- self.isTransport = false;
	if self.mowerParticleSystemsRight ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsRight, false);
	end; 
	if self.mowerParticleSystemsLeft ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsLeft, false);
	end; 
end;

function TaarupMower:onLeave()

	if self.deactivateOnLeave then
          TaarupMower.onDeactivate(self);
      else
          TaarupMower.onDeactivateSounds(self)
      end;
	if self.mowerParticleSystemsRight ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsRight, false);
	end; 
	if self.mowerParticleSystemsLeft ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsLeft, false);
	end; 	
end;

function TaarupMower:onDeactivate()
    TaarupMower.onDeactivateSounds(self)
	self.isTurnedOn = false;	
	if self.mowerParticleSystemsRight ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsRight, false);
	end; 
	if self.mowerParticleSystemsLeft ~= nil then
		Utils.setEmittingState(self.mowerParticleSystemsLeft, false);
	end;	
end;

function TaarupMower:onDeactivateSounds()
      if self.isClient then
		if self.rotarySoundEnabled then
			stopSample(self.rotarySound);
			self.rotarySoundEnabled = false;
		end;
     end;
end;

function TaarupMower:setVehicleRpmUp(dt, isActive)
	if self.attacherVehicle ~= nil and self.saveMinRpm ~= 0 then
		if dt ~= nil then
			if isActive == true then
				self.attacherVehicle.motor.minRpm = math.max(self.attacherVehicle.motor.minRpm-dt, -1000);
			else
				self.attacherVehicle.motor.minRpm = math.min(self.attacherVehicle.motor.minRpm+dt*2, self.saveMinRpm);
			end;
		else
			self.attacherVehicle.motor.minRpm = self.saveMinRpm;
		end;
		if self.attacherVehicle.isMotorStarted then
			local fuelUsed = 0.00000011*math.abs(self.attacherVehicle.motor.minRpm);
			self.attacherVehicle:setFuelFillLevel(self.attacherVehicle.fuelFillLevel-fuelUsed);
			g_currentMission.missionStats.fuelUsageTotal = g_currentMission.missionStats.fuelUsageTotal + fuelUsed;
			g_currentMission.missionStats.fuelUsageSession = g_currentMission.missionStats.fuelUsageSession + fuelUsed;
		end;
	end;
end;


function TaarupMower:setTransport(isTransport, noEventSend)
	SetTransportEvent.sendEvent(self, isTransport, noEventSend);
	for _, foldingPart in pairs(self.mowerFoldingParts) do			
		foldingPart.isDown = not isTransport;
	end;
	self.isTransport = isTransport;
	
	if isTransport then
		if self.isTurnedOn then
			self:setIsTurnedOn(false);-- self:setIsTurnedOn(false, true);
		end;						
	end;	

end;

function TaarupMower:setIsArmDown(arm, isDown, noEventSend)
	local foldingArm = self.mowerFoldingParts[arm];
	if foldingArm ~= nil then
		SetIsArmDownEvent.sendEvent(self, arm, isDown, noEventSend);
		foldingArm.mainPart.isDown = isDown;
	end;
end;

function TaarupMower:getIsAreaActive(superFunc, area)
	local isActive = false;
	local mowerByArea = nil;
	for _, foldingPart in pairs(self.mowerFoldingParts) do
		if foldingPart.mower.cuttingArea == area then
			mowerByArea = foldingPart;
			break;
		end;
	end;
	if mowerByArea ~= nil then
		isActive = true;
		for i=1, 3 do
			isActive = isActive and mowerByArea.mower.currentLimit[i] >= mowerByArea.mower.maxLimit[i] * 0.5;
		end;	
	end;
    if superFunc ~= nil then
        return superFunc(self, area) and isActive;
    end;
	return isActive;	
end;
