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

	self.setTransRot = SpecializationUtil.callSpecializationsFunction("setTransRot");
	self.TransRotAnimation = getXMLString(xmlFile, "vehicle.TransRot#animationName");
	self.TransRot = false;
	self.setArmOne = SpecializationUtil.callSpecializationsFunction("setArmOne");
	self.ArmOneAnimation = getXMLString(xmlFile, "vehicle.armOne#animationName");
	self.ArmOne = false;
	
    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.printWarningTime1 = 0;
	self.lastArea = 0;
	self.lastAreaBiggerZero = self.lastArea > 0;
 	self.setVehicleRpmUp = SpecializationUtil.callSpecializationsFunction("setVehicleRpmUp");
	self.saveMinRpm = 0; 

end;

function KevKDMower:delete()
	Utils.deleteParticleSystem(self.mowerParticleSystems);
	
	if self.rotarySound ~= nil then
		delete(self.rotarySound);
	end;
 
end;
  
function KevKDMower:readStream(streamId, connection)
	  
    local turnedOn = streamReadBool(streamId);
    self:setIsTurnedOn(turnedOn, true);
	  
    self:setTransRot(streamReadBool(streamId), true);
	self:setArmOne(streamReadBool(streamId), true);
	
	self.lastAreaBiggerZero = streamReadBool(streamId);

end;
  
function KevKDMower:writeStream(streamId, connection)

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

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

end;
  
function KevKDMower:update(dt)
  
    if self:getIsActiveForInput() then
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
              self:setIsTurnedOn(not self.isTurnedOn);
        end;
		if not self.isArmOneOn then		
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
				self:setTransRot(not self.isTransRotOn);
			end;
		end;
		if InputBinding.isPressed(InputBinding.IMPLEMENT_EXTRA) and self.PTOId then
				self.printWarningTime1 = self.time + 1500;
		end;
	end;
    if self:getIsActive() then 
		if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
			if not self.isTransRotOn then			
				if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
					self:setArmOne(not self.isArmOneOn);					
				end;	
			end;
		end;
    end;
end;
  
function KevKDMower:updateTick(dt)

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

	
		if self.isTransRotOn 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 and self.isArmOneOn then
		
            local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31;
            if not toFast 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 self.isArmOneOn 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 KevKDMower: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 self.isArmOneOn 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 not self.isArmOneOn then	
			if not 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;
		end;
		if not self.isTransRotOn then 		
			if self.isArmOneOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("raise"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("lower"), self.typeDesc), InputBinding.LOWER_IMPLEMENT);
			end;
		end;		
		if self.printWarningTime1 > self.time then
			g_currentMission:addWarning(g_i18n:getText("turnON_Error"), 0.018, 0.033);
		end;
    end;
end;
  
function KevKDMower:onDetach()
      if self.deactivateOnDetach then
          KevKDMower.onDeactivate(self);
      else
          KevKDMower.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;
	self:setTransRot(false);
end;

function KevKDMower:onAttach(attacherVehicle)
	self.attacherVehicle = attacherVehicle;
	if self.attacherVehicleCopy == nil then
		self.attacherVehicleCopy = self.attacherVehicle;
	end;
	self.saveMinRpm = self.attacherVehicle.motor.minRpm;
end;
  
function KevKDMower:onLeave()
	if self.mowerParticleSystems ~= nil then
		Utils.setEmittingState(self.mowerParticleSystems, false);
	end; 

	if self.deactivateOnLeave then
          KevKDMower.onDeactivate(self);
      else
          KevKDMower.onDeactivateSounds(self)
      end;
	self:setIsTurnedOn(false, true);

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

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

function KevKDMower: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 KevKDMower: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 KevKDMower:setArmOne(isArmOne,noEventSend)
	SetArmOneEvent.sendEvent(self, isArmOne, noEventSend);
	-- Play ArmOne animation --
	self.isArmOneOn = isArmOne;
	if self.isArmOneOn then
		if self.ArmOneAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmOneAnimation, -1, nil, true);
			self.ArmOne = true;
		end;
	else
		if self.ArmOneAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.ArmOneAnimation, 1, nil, true);
			self.ArmOne = false;
		end;
	end;	
end;
