-- NI Modding
--
-- author  	Henly20 
-- date  	03-03-2013.
-- ni_modding@hotmail.com
-- http://nimodding.wordpress.com
  
KevMT = {};
  
function KevMT.prerequisitesPresent(specializations)
    return true;
end;
  
function KevMT:load(xmlFile)

	self.setTransRot = SpecializationUtil.callSpecializationsFunction("setTransRot");
	self.TransRotAnimation = getXMLString(xmlFile, "vehicle.TransRot#animationName");
	self.TransRot = false;
	self.setWheelRot = SpecializationUtil.callSpecializationsFunction("setWheelRot");
	self.WheelRotAnimation = getXMLString(xmlFile, "vehicle.WheelRot#animationName");
	self.WheelRot = false;
	self.setSideSkirts = SpecializationUtil.callSpecializationsFunction("setSideSkirts");
	self.SideSkirtsAnimation = getXMLString(xmlFile, "vehicle.SideSkirts#animationName");
	self.SideSkirts = false;
	self.sideskirtNode = {};
	self.sideskirtNode.node  = Utils.indexToObject(self.components,getXMLString(xmlFile, "vehicle.sideskirtNode#index"));	
	
    self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
	
    self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 1);
    self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
    if self.groundReferenceNode == nil then
        self.groundReferenceNode = self.components[2].node;
    end;
	
      self.mowerCutAreasSend = {};
      self.mowerCutAreas = {}
      local i=0;
      while true do
          local areaKey = string.format("vehicle.mowerCutAreas.mowerCutArea(%d)", i);
          if not hasXMLProperty(xmlFile, areaKey) then
              break;
          end
          local area = {};
          if self:loadAreaFromXML(area, xmlFile, areaKey) then
              area.dropWindrow = Utils.getNoNil(getXMLBool(xmlFile, areaKey .. "#dropWindrow"), true);
              area.dropArea = getXMLInt(xmlFile, areaKey .. "#dropArea");
              if area.dropArea ~= nil and self.mowerWindrowDropAreas[area.dropArea] == nil then
                  area.dropArea = nil;
              end
              table.insert(self.mowerCutAreas, area);
              table.insert(self.mowerCutAreasSend, {});
          end
          i = i + 1;
      end
  
      -- fallback: load in cutting areas
      if table.getn(self.mowerCutAreas) == 0 then
          for _, cuttingArea in pairs(self.cuttingAreas) do
              cuttingArea.dropWindrow = true;
              table.insert(self.mowerCutAreas, cuttingArea);
              table.insert(self.mowerCutAreasSend, {});
          end
      end  
      self.isTurnedOn = false;
      self.wasToFast = false;
      
      self.mowerGroundFlag = self.nextDirtyFlag;
      self.nextDirtyFlag = self.mowerGroundFlag*2;

	  self.mowerParticleSystems = {};
      local i = 0;
      while true do
        local namei = string.format("vehicle.mowerParticleSystems.mowerParticleSystems(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
        Utils.loadParticleSystem(xmlFile, self.mowerParticleSystems, namei, nodei, false, nil, self.baseDirectory)		
		i = i +1;		
      end;
  
     self.onlyActiveWhenLowered = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.onlyActiveWhenLowered#value"), 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.sideSkirtsDown = {};
      local i = 0;
      while true do
          local key = string.format("vehicle.sideSkirtsDown.sideskirtsdown(%d)", i);
          if not hasXMLProperty(xmlFile, key) then
              break;
          end;
          local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
           if node ~= nil then
              setVisibility(node, false);
              table.insert(self.sideSkirtsDown, {node=node});
          end;
          i = i + 1;
      end; 
	
      self.sideSkirtsUp = {};
      local i = 0;
      while true do
          local key = string.format("vehicle.sideSkirtsUp.sideskirtsup(%d)", i);
          if not hasXMLProperty(xmlFile, key) then
              break;
          end;
          local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
          if node ~= nil then
              setVisibility(node, true);
              table.insert(self.sideSkirtsUp, {node=node});
          end;
          i = i + 1;
      end;
	
    self.printWarningTime = 0;
    self.printWarningTime1 = 0;
	self.lastArea = 0;
	self.lastAreaBiggerZero = self.lastArea > 0;
 	self.setVehicleRpmUp = SpecializationUtil.callSpecializationsFunction("setVehicleRpmUp");
	self.saveMinRpm = 0; 
end;

function KevMT:delete()
	Utils.deleteParticleSystem(self.mowerParticleSystems);
	
	if self.rotarySound ~= nil then
		delete(self.rotarySound);
	end;
 
end;

function KevMT:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		if self.SideSkirtsAnimation ~= nil then
			local isSideSkirtsOn = 	getXMLBool(xmlFile, key.."#isSideSkirtsOn");
			if isSideSkirtsOn ~= nil then
				self:setSideSkirts(isSideSkirtsOn, true);
				if self.playAnimation ~= nil then
					AnimatedVehicle.updateAnimationByName(self, self.SideSkirtsAnimation, 99999999);
					if self.updateCylinderedInitial ~= nil then
						self:updateCylinderedInitial();
					end
				end
			end;
		end;
		local CondPanel = Utils.getNoNil(getXMLBool(xmlFile, key .. "#CondPanel"), false);
		if CondPanel ~= nil then
			self:setCondPanel(CondPanel);
		end;
	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function KevMT:getSaveAttributesAndNodes(nodeIdent)
	local attributes = ' ';

	local mystring = 'isSideSkirtsOn="' .. tostring(self.isSideSkirtsOn) ..'"';	
	attributes = attributes .. mystring;

	local mystring = 'CondPanel="' .. tostring(self.CondPanel) ..'"';	
	attributes = attributes .. mystring;
	
    local node = nil;
	return attributes, node;
end;
  
function KevMT:readStream(streamId, connection)
	  
    local turnedOn = streamReadBool(streamId);
    self:setIsTurnedOn(turnedOn, true);
	  
    self:setWheelRot(streamReadBool(streamId), true); 
    self:setTransRot(streamReadBool(streamId), true);
    self:setSideSkirts(streamReadBool(streamId), true);
	
	self.lastAreaBiggerZero = streamReadBool(streamId);

end;
  
function KevMT:writeStream(streamId, connection)

    streamWriteBool(streamId, self.isTurnedOn);
	  
    streamWriteBool(streamId, self.WheelRot);
    streamWriteBool(streamId, self.TransRot);
    streamWriteBool(streamId, self.SideSkirts);
	
	streamWriteBool(streamId, self.lastAreaBiggerZero);
end;
  
function KevMT:readUpdateStream(streamId, timestamp, connection)
	if connection:getIsServer() then
		self.lastAreaBiggerZero = streamReadBool(streamId);

	end;
end;
  
function KevMT:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection:getIsServer() then
		streamWriteBool(streamId, self.lastAreaBiggerZero);
	end;
end;
  
function KevMT:mouseEvent(posX, posY, isDown, isUp, button)
end;
  
function KevMT:keyEvent(unicode, sym, modifier, isDown)

end;
  
function KevMT:update(dt)

	if not self:getIsActive() then
		if self.sideskirtInRange and not self.isTransRotOn then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
				self:setSideSkirts(not self.isSideSkirtsOn);
			end;
			if self.isSideSkirtsOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("transport"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("field"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			end;
		end;
	end;
	 
    if self:getIsActive() then 
		if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) and self.isSideSkirtsOn then
				self:setTransRot(not self.isTransRotOn);
			end;
			if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
				self:setWheelRot(not self.isWheelRotOn);
			end;
		end;
		if self.isClient and self:getIsActiveForInput() and not self:hasInputConflictWithSelection() then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
				self:setIsTurnedOn(not self.isTurnedOn);
			end;
			if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA2) and not self.isSideSkirtsOn then
					self.printWarningTime = self.time + 1500;
				end;
			if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) and self.PTOId then
					self.printWarningTime1 = self.time + 1500;
			end;
		end;
	end;	 
end;
  
function KevMT:updateTick(dt)
		
		if g_currentMission.player ~= nil then
			local nearestDistance = 3;
			local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);		
			local px, py, pz = getWorldTranslation(self.sideskirtNode.node); 
			local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);	
			if distance < nearestDistance then
				self.sideskirtInRange = true; 
			else
				self.sideskirtInRange = false; 
			end;
		end;

    self.wasToFast = false;
	self.lastArea = 0;	
    if self:getIsActive() then

		if not self.attacherVehicle.isMotorStarted then
			self.isTurnedOn = false;
		end;
		if self.PTOId then
			self.isTurnedOn = false;
		end;
		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;
        if self.isTurnedOn and self.isServer then
			
              local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31;
              if not toFast and not self.isWheelRotOn then
                  if self.isServer then
                      local x,y,z = getWorldTranslation(self.groundReferenceNode);
                      local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
                      if terrainHeight+self.groundReferenceThreshold >= y then
                          local numAreasSend = 0;
                          local numDropAreas = 0;
                          local areasSend = self.mowerCutAreasSend;
                          for _,area in pairs(self.mowerCutAreas) do
                              if self:getIsAreaActive(area) then
                                  numAreasSend = numAreasSend + 1;
                                  areasSend[numAreasSend].x,_,areasSend[numAreasSend].z = getWorldTranslation(area.start);
                                  areasSend[numAreasSend].x1,_,areasSend[numAreasSend].z1 = getWorldTranslation(area.width);
                                  areasSend[numAreasSend].x2,_,areasSend[numAreasSend].z2 = getWorldTranslation(area.height);
                                  areasSend[numAreasSend].dropWindrow = area.dropWindrow;
                                  areasSend[numAreasSend].dropArea = area.dropArea;
                                  if self.useMowerWindrowDropAreas then
                                      areasSend[numAreasSend].dropWindrow = true;
                                  else
                                      areasSend[numAreasSend].dropArea = nil;
                                  end
                              end
                          end					  						  
						  
                          if numAreasSend > 0 then
                              local numAreasUsed, numDropAreasUsed, pickedUpWindrow = MowerAreaEvent.runLocally(areasSend, numAreasSend, self.mowerWindrowDropAreas, numDropAreas);

							self.lastArea = numAreasUsed;
							self.lastAreaBiggerZero = (self.lastArea > 0);
                              if numAreasUsed > 0 or numDropAreasUsed > 0 then
                                  g_server:broadcastEvent(MowerAreaEvent:new(areasSend, numAreasUsed, self.mowerWindrowDropAreas, numDropAreas, numDropAreasUsed));
                              end
							end;
                      end;
                  end;
              end;
  
              if self.isClient then
                  if not self.mowerSoundEnabled and self:getIsActiveForSound() then
                      setSamplePitch(self.mowerSound, self.mowerSoundPitchOffset);
                      playSample(self.mowerSound, 0, self.mowerSoundVolume, 0);
                      self.mowerSoundEnabled = true;
                  end;
              end;
  
              self.wasToFast = toFast;
  
          else
              if self.isClient then
                  if self.mowerSoundEnabled then
                      stopSample(self.mowerSound);
                      self.mowerSoundEnabled = false;
                  end;
              end;
          end;
			
			if self.isTurnedOn and self.movingDirection ~= 0 and not self.isWheelRotOn and self.lastAreaBiggerZero then
				Utils.setEmittingState(self.mowerParticleSystems, true);
			else
				Utils.setEmittingState(self.mowerParticleSystems, false);
			end;

      end;
	
	for i, jointDesc in pairs(self.componentJoints) do
	   setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
	end;
end;
  
function KevMT:draw()
      if self.isClient then
		if not self.PTOId then
			if self.isTurnedOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
			end;
		end;
        if self.wasToFast and not self.isWheelRotOn 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;
        if self.isTransRotOn then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("transport"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
        else
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("field"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
        end;
        if self.isWheelRotOn then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("lower"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
        else
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("raise"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
        end;
		if self.printWarningTime > self.time then
			g_currentMission:addWarning(g_i18n:getText("bodyRotate_Error"), 0.018, 0.033);
		end;
		if self.printWarningTime1 > self.time then
			g_currentMission:addWarning(g_i18n:getText("turnON_Error"), 0.018, 0.033);
		end;
    end;
	
end;
  
function KevMT:onDetach()
      if self.deactivateOnDetach then
          KevMT.onDeactivate(self);
      else
          KevMT.onDeactivateSounds(self)
      end;
	if self.mowerParticleSystems ~= nil then
		Utils.setEmittingState(self.mowerParticleSystems, false);
	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;
end;

function KevMT:onAttach(attacherVehicle)

	self.attacherVehicle = attacherVehicle;
	if self.attacherVehicleCopy == nil then
		self.attacherVehicleCopy = self.attacherVehicle;
	end;
	self.saveMinRpm = self.attacherVehicle.motor.minRpm;

end;
  
function KevMT:onLeave()
	if self.mowerParticleSystems ~= nil then
		Utils.setEmittingState(self.mowerParticleSystems, false);
	end; 

 if self.deactivateOnLeave then
          KevMT.onDeactivate(self);
      else
          KevMT.onDeactivateSounds(self)
      end;

	  self:setIsTurnedOn(false, true);

end;
  
function KevMT:onDeactivate()
      KevMT.onDeactivateSounds(self)
 
	  self:setIsTurnedOn(false, true);
	if self.mowerParticleSystems ~= nil then
		Utils.setEmittingState(self.mowerParticleSystems, false);
	end; 
end;
  
function KevMT:onDeactivateSounds()
      if self.isClient then
		if self.rotarySoundEnabled then
			stopSample(self.rotarySound);
			self.rotarySoundEnabled = false;
		end;
     end;
end;

function KevMT:validateAttacherJoint(implement, jointDesc, dt)
    return true;
end;
  
function KevMT:setIsTurnedOn(turnedOn, noEventSend)
      SetTurnedOnEvent.sendEvent(self, turnedOn, noEventSend)
      self.isTurnedOn = turnedOn;
end;

function KevMT: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 KevMT:setWheelRot(isWheelRot,noEventSend)
	SetWheelRotEvent.sendEvent(self, isWheelRot, noEventSend);
	-- Play WheelRot animation --
	self.isWheelRotOn = isWheelRot;
	if self.isWheelRotOn then
		if self.WheelRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.WheelRotAnimation, 1, nil, true);
			self.WheelRot = true;

		end;
	else
		if self.WheelRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.WheelRotAnimation, -1, nil, true);
			self.WheelRot = false;
	
		end;
	end;
end;

function KevMT:setTransRot(isTransRot,noEventSend)
	SetTransRotEvent.sendEvent(self, isTransRot, noEventSend);
	-- Play TransRot animation --
	self.isTransRotOn = isTransRot;
	if self.isTransRotOn then
		if self.TransRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.TransRotAnimation, 1, nil, true);
			self.TransRot = true;
		end;
	else
		if self.TransRotAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.TransRotAnimation, -1, nil, true);
			self.TransRot = false;
		end;
	end;	
end;

function KevMT:setSideSkirts(isSideSkirts,noEventSend)
	SetSideSkirtsEvent.sendEvent(self, isSideSkirts, noEventSend);
	-- Play SideSkirts animation --
	self.isSideSkirtsOn = isSideSkirts;
	if self.isSideSkirtsOn then
		if self.SideSkirtsAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.SideSkirtsAnimation, 1, nil, true);
			self.SideSkirts = true;
			for _, sideskirtsdown in pairs(self.sideSkirtsDown) do
				setVisibility(sideskirtsdown.node, true);
			end;
			for _, sideskirtsup in pairs(self.sideSkirtsUp) do
				setVisibility(sideskirtsup.node, false);
			end;
		end;
	else
		if self.SideSkirtsAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.SideSkirtsAnimation, -1, nil, true);
			self.SideSkirts = false;
			self.SideSkirtsScale = false;
			for _, sideskirtsdown in pairs(self.sideSkirtsDown) do
				setVisibility(sideskirtsdown.node, false);
			end;
			for _, sideskirtsup in pairs(self.sideSkirtsUp) do
				setVisibility(sideskirtsup.node, true);

			end;			  
		end;
	end;


end;
