RealisticCombine = {};

function RealisticCombine.prerequisitesPresent(specializations) 
	return SpecializationUtil.hasSpecialization(RealisticVehicle, specializations);
end;


function RealisticCombine:load(xmlFile)

	self.isRealistic = true;
	self.isRealisticCombine = true;
	
	self.realOnDesactivatePS = SpecializationUtil.callSpecializationsFunction("realOnDesactivatePS");
	self.getIsStartThreshingAllowed = RealisticCombine.getIsStartThreshingAllowed;

	self.realThreshingPowerConsumption = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realThreshingPowerConsumption"), 0);
	self.realThreshingPowerConsumptionInc = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realThreshingPowerConsumptionInc"), 0);
	self.realChopperPowerConsumption = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realChopperPowerConsumption"), 0);	
	self.realChopperPowerConsumptionInc = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realChopperPowerConsumptionInc"), 0);
	
	self.realCombineCycleDuration = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realCombineCycleDuration"), 3); -- duration of the threshing cycle in second
	
	self.realCombineUnloadingNeedsEngineRev = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.realCombineUnloadingNeedsEngineRev"), true);
	
	--self.realCombineMaxThreshingSpeed = getXMLFloat(xmlFile, "vehicle.realCombineMaxThreshingSpeed"); -- max sqm per second possible to thresh (example for a combine harvester : 8kph * 8m cut wide = 17.78m2 per second / 35.6m2 per second with fertilized crop) 
	
	--if self.realCombineMaxThreshingSpeed==nil then
	--	RealisticUtils.printWarning("RealisticCombine:load", self.realVehicleName .. " - realCombineMaxThreshingSpeed is not define in the xml file for this combine - you should set it - example for a combine harvester : 8kph * 8m cut wide = 17.78m2 per second / 35.6m2 per second with fertilized crop", false)
	--	self.realCombineMaxThreshingSpeed=10;
	--end;
	
	--local incPeriod = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realIncPeriod"), 3);
	--if incPeriod<0.02 then
	--	self.realIncFreq = 1/3;
	--else	
	--	self.realIncFreq = 1/incPeriod;
	--end;
	
	self.realUnloadingPowerConsumption = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realUnloadingPowerConsumption"), 0);
	self.realUnloadingPowerBoost = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realUnloadingPowerBoost"), 0);
	self.realThreshingPowerBoost = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realThreshingPowerBoost"), 0);
	
	self.realCombineGrainTankLevelPercentForBeaconLight = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realCombineGrainTankLevelPercentForBeaconLight"), 0.75); -- set this value over 1 if you don't want the combine to ligh on the beacon light when the grain tank is nearly full (example : older combines do not have this feature)
			
	--override default threshing scale
	self.threshingScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realThreshingScale"), 1);
	
	--overriding the default values	
	self.waitForTurnTimeout = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.waitForTurnTime"), 2000); -- wait more for straw to be deposed on the ground
	self.pipeParticleSystemExtraDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipeParticleSystems#extraDistance"), 2);

	
	
	self.realGetIsWorkingTooFast = RealisticCombine.realGetIsWorkingTooFast;
	
		
	self.realCurrentPowerConsumption = 0;	
	self.realCuttersPowerConsumptionInc = 0;
	self.realCombineMaterialQty = 0;
	
	self.realCombineSqmBeingThreshed = 0;
	
	--backing up drop areas
	local i1 = 0;
	self.realGenStrawAreas = {};
	if self.strawAreas ~= nil then
		for k, strawArea in pairs(self.strawAreas) do
			i1 = i1 + 1;
			self.realGenStrawAreas[i1] = {};
			local x,y,z = getTranslation(strawArea.start);
			self.realGenStrawAreas[i1].start = {x=x, y=y, z=z};
			x,y,z = getTranslation(strawArea.width);
			self.realGenStrawAreas[i1].width = {x=x, y=y, z=z};
			x,y,z = getTranslation(strawArea.height);
			self.realGenStrawAreas[i1].height = {x=x, y=y, z=z};
		end;
	end;
	

end;

function RealisticCombine:delete()    
end;

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

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

function RealisticCombine:updateTick(dt)

	if self.isServer then

		if self.firstTimeRun and self.grainTankFillLevel then
			local found, density, pricePerKg = RealisticUtils.getFillTypeInfosV2(Fillable.fillTypeIntToName[FruitUtil.fruitTypeToFillType[self.currentGrainTankFruitType]]);
			self.realGrainTankFillMass = self.grainTankFillLevel*0.001*density;		
		end;	
	
		if self.isThreshing then				
			--print(self.time .. " RealisticCombine:updateTick - dt = " .. dt .. " / self.lastArea = " .. self.lastArea );		
			--add last cut area material "into the combine"	
			local materialFx = 1;
			if self.lastInputFruitType~=FruitUtil.FRUITTYPE_UNKNOWN then
				materialFx = RealisticUtils.getCropMaterialQtyFx(FruitUtil.fruitIndexToDesc[self.lastInputFruitType].name);
			end;
			self.realCombineSqmBeingThreshed = self.realCombineSqmBeingThreshed + materialFx*self.lastArea*g_currentMission:getFruitPixelsToSqm();		
			RealisticCombine.realStrawAreasCorrection(self);
		end;
		
	end;
	
end;



function RealisticCombine:update(dt)

	local pwrCons = 0;
	local powerConsumptionInc = 0;
	
	if self.isServer then
		self.realToolNeedEngineRev = false;
		if self.isActive then
			
			local totalBoost = 0;
			
			--we assume a combine is a box where material enters and goes out in some time

			if self.isThreshing then
				
				pwrCons = self.realThreshingPowerConsumption;				
				totalBoost = self.realThreshingPowerBoost;
				
				--adding cut material into the "box"
				--self.realCombineMaterialQty = self.realCombineMaterialQty + 0.01*self.lastArea*g_currentMission:getFruitPixelsToSqm(); -- 4096px are mapped to 2048m				
							
				powerConsumptionInc = self.realThreshingPowerConsumptionInc + self.realCuttersPowerConsumptionInc;
				if self.chopperActivated then
					pwrCons = pwrCons + self.realChopperPowerConsumption;
					powerConsumptionInc = powerConsumptionInc + self.realChopperPowerConsumptionInc;
				end;		

				
				--print(self.time .. " RealisticCombine:update - realCombineMaterialQty = " .. tostring(self.realCombineMaterialQty) .. " / self.lastArea = " .. tostring(self.lastArea));
				
				--reducing the "realCombineSqmBeingThreshed"				
				--print(self.time .. " RealisticCombine:update - threshingSpeed = " .. tostring(threshingSpeed) .. " / realCombineSqmBeingThreshed = " .. tostring(self.realCombineSqmBeingThreshed));				
				self.realCombineSqmBeingThreshed = self.realCombineSqmBeingThreshed*(1 - dt/1000/self.realCombineCycleDuration);
				if self.realCombineSqmBeingThreshed<0.01 then
					self.realCombineSqmBeingThreshed = 0;
				end;
				
				--powerConsumptionInc = powerConsumptionInc*self.realCombineMaterialQty*self.realIncFreq;	--self.realCombineMaterialQty*self.realIncFreq = estimation of the throughput in liters/second (only grain)
				powerConsumptionInc = powerConsumptionInc*self.realCombineSqmBeingThreshed/self.realCombineCycleDuration;
				--print(self.time .. " RealisticCombine:update - powerConsumptionInc = " .. tostring(powerConsumptionInc) .. " / lastArea = " .. tostring(self.lastArea) .. " / realCombineSqmBeingThreshed=" .. tostring(self.realCombineSqmBeingThreshed));
			end;
			
			if self.pipeIsUnloading then
				pwrCons = pwrCons + self.realUnloadingPowerConsumption;
				totalBoost = totalBoost + self.realUnloadingPowerBoost;	
				if self.realCombineUnloadingNeedsEngineRev then
					self.realToolNeedEngineRev = true;
				end;
			end;
		
			self.realCurrentPowerBoost2 = totalBoost;
			self.realCurrentPowerConsumption = pwrCons + powerConsumptionInc;
			
		else		
			self.realCurrentPowerConsumption = 0;					
		end;
		
	end;

end;

function RealisticCombine:draw()
end;




function RealisticCombine:attachImplement(implement)

	--** update powerConsumptionInc
	RealisticCombine.updatePowerConsumptionInc(self);

end;

function RealisticCombine:detachImplement(implementIndex)
	
	--** update powerConsumptionInc
	RealisticCombine.updatePowerConsumptionInc(self);
	
end;



function RealisticCombine:updatePowerConsumptionInc()

	self.realCuttersPowerConsumptionInc = 0;
	if self.attachedCutters~=nil then
		for cutter, implement in pairs(self.attachedCutters) do
			--print("cutter : " .. tostring(cutter) .. " isRealistic ? " .. tostring(cutter.isRealistic));
			if cutter.isRealistic and not cutter.isRealisticCombine then
				--print("-----cutter power inc : " .. tostring(cutter.realPowerConsumptionInc));
				self.realCuttersPowerConsumptionInc = self.realCuttersPowerConsumptionInc + cutter.realCutterPowerConsumptionInc;
			end;
		end;
	end;
	--print("self.realCuttersPowerConsumptionInc = " .. self.realCuttersPowerConsumptionInc );
	
end;

function RealisticCombine:realGetIsWorkingTooFast()

	local isWorkingTooFast = false;
	local maxSpeedAllowed = 99999;
	
	if self.attachedCutters~=nil then
		for cutter, _ in pairs(self.attachedCutters) do
			if cutter.isRealisticCutter then
				if math.abs(cutter.speedViolationTimer - cutter.speedViolationMaxTime) > 200 then
					maxSpeedAllowed = math.min(maxSpeedAllowed, cutter.realCutterSpeedLimit);
					isWorkingTooFast = true;
				end;
			end;
		end;
	end;
	
	return isWorkingTooFast, maxSpeedAllowed;
end;


function RealisticCombine.realStrawAreasCorrection(self)

	local i = 1;
	if self.strawAreas~=nil then
		for k, strawArea in pairs(self.strawAreas) do
			RealisticUtils.realAreaCorrection(self, strawArea, self.realGenStrawAreas[i]);
			i = i + 1;
		end;
	end;
	
end;



function RealisticCombine:getIsStartThreshingAllowed()

	--if not self.realIsMotorStarted then	
	if not self.isMotorStarted then
		if self.attacherVehicle~=nil then 				
			if not self.attacherVehicle.isMotorStarted then
				return false; --trailed harvester, attacher vehicle motor not started
			end;
		else
			--self propelled harvester, self.isMotorStarted==false or nil
			return false;
		end;			
	end;	
	
	return Combine.getIsStartThreshingAllowed(self);
	
end;


function RealisticCombine:realOnDesactivatePS()
	
	if self.setChopperPSEnabled then
		self:setChopperPSEnabled(false, false, true);
	end;
	if self.setStrawPSEnabled then
		self:setStrawPSEnabled(false, false, true);
	end;
	
end;




