--
-- E302_Cutter specialization
-- @author		Burner
-- @date		21.09.2011
--

E302_Cutter = {};

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

function E302_Cutter:load(xmlFile)
	self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
	
    self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.5);
    self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
    if self.groundReferenceNode == nil then
        self.groundReferenceNode = self.components[1].node;
    end;

    local mowerSound = getXMLString(xmlFile, "vehicle.mowerSound#file");
    if mowerSound ~= nil and mowerSound ~= "" then
        mowerSound = Utils.getFilename(mowerSound, self.baseDirectory); 
        self.mowerSound = createSample("mowerSound");
        self.mowerSoundEnabled = false;
        loadSample(self.mowerSound, mowerSound, false);
        self.mowerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#pitchOffset"), 1);
        self.mowerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#volume"), 1);
    end;

    local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.windrowerCuttingAreas#count"), 0);
    self.windrowerCuttingAreas = {};
	self.accumulatedCuttingAreaValues = {};
    for i=1, numCuttingAreas do
        self.windrowerCuttingAreas[i] = {};
        local areanamei = string.format("vehicle.windrowerCuttingAreas.cuttingArea%d", i);
        self.windrowerCuttingAreas[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex"));
        self.windrowerCuttingAreas[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex"));
        self.windrowerCuttingAreas[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex"));
		self.accumulatedCuttingAreaValues[i] = 0;
	end;
	
    local numWindrowerDropAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.windrowerDropAreas#count"), 0);
    if numWindrowerDropAreas == 0 then
        print("Warning: No drop areas specified in '"..self.configFileName.."'");
    else
        if numWindrowerDropAreas ~= 1 and numWindrowerDropAreas ~= table.getn(self.windrowerCuttingAreas) then
            print("Warning: Number of cutting areas and drop areas should be equal in '"..self.configFileName.."'");
        end;
    end;
    self.windrowerDropAreas = {}
	self.accumulatedCuttingAreaValues = {};
    for i=1, numWindrowerDropAreas do
        self.windrowerDropAreas[i] = {};
        local areanamei = string.format("vehicle.windrowerDropAreas.windrowerDropArea%d", i);
        self.windrowerDropAreas[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex"));
        self.windrowerDropAreas[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex"));
        self.windrowerDropAreas[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex"));
		self.accumulatedCuttingAreaValues[i] = 0;
    end;

    self.isTurnedOn = false;
    self.wasToFast = false;
    self.forog = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.forog#index"));
    self.reelNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.reel#index"));

	self.cutterParticleSystems = {};
	local i=0;
	while true do
		local key = string.format("vehicle.cutterParticleSystems.cutterParticleSystem(%d)", i);
		local node = getXMLString(xmlFile, key.. "#node");
		if node == nil then
			break;
		end;
		node = Utils.indexToObject(self.components, node);
		if node ~= nil then
			local psFile = getXMLString(xmlFile, key.. "#file");
			local psType = getXMLString(xmlFile, key .. "#type");
			local psDesc = FruitUtil.fruitTypes[psType];
			if psDesc ~= nil then
				local cutterParticleSystem = {};
				cutterParticleSystem.particleSystem = {};
				local isStatic = Utils.getNoNil(getXMLBool(xmlFile, key.."#static"), false);
				if isStatic then
					StaticParticleSystem.loadParticleSystem(xmlFile, cutterParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
				else
					Utils.loadParticleSystem(xmlFile, cutterParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
				end;
				self.cutterParticleSystems[psDesc.index] = cutterParticleSystem;
			end;
		end;
		i = i+1;
	end;
	
	self.dustParticleSystems = {};
	local i=0;
	while true do
		local key = string.format("vehicle.dustParticleSystems.dustParticleSystem(%d)", i);
		local node = getXMLString(xmlFile, key.. "#node");
		if node == nil then
			break;
		end;
		node = Utils.indexToObject(self.components, node);
		if node ~= nil then
			local psFile = getXMLString(xmlFile, key.. "#file");
			local psType = getXMLString(xmlFile, key .. "#type");
			local psDesc = FruitUtil.fruitTypes[psType];
			if psDesc ~= nil then
				local dustParticleSystem = {};
				dustParticleSystem.particleSystem = {};
				Utils.loadParticleSystem(xmlFile, dustParticleSystem.particleSystem, key, self.components, false, nil, self.baseDirectory);
				self.dustParticleSystems[psDesc.index] = dustParticleSystem;
			end;
		end;
		i = i+1;
	end;
	
	local indexSpikesStr = getXMLString(xmlFile, "vehicle.reelspikes#index");
	self.spikesCount = getXMLInt(xmlFile, "vehicle.reelspikes#count");
	self.spikesRootNode = Utils.indexToObject(self.components, indexSpikesStr);
	
	self.extraRollNodes = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.extraRolls.roll(%d)", i);
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
        local rollNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
		local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#speed"));
        if rollNode ~= nil then
			local speed = {};
			speed.x = Utils.getNoNil(x, 0);
			speed.y = Utils.getNoNil(y, 0);
			speed.z = Utils.getNoNil(z, 0);
            table.insert(self.extraRollNodes, {node=rollNode, speed=speed});
        end;
        i = i + 1;
    end;
		
	self.fruitTypes = {};
	self.fruitTypes[FruitUtil.FRUITTYPE_UNKNOWN] = true;
	self.fruitOutputTypes = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.fruitTypes.fruitType(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local inputType = getXMLString(xmlFile, key .. "#input");
		local outputType = getXMLString(xmlFile, key .. "#output");
		if outputType ~= "cut_long" and outputType ~= "windrow" then
			outputTypeDesc = "windrow";
		else
			outputTypeDesc = outputType;
		end;
		if inputType ~= nil and outputTypeDesc ~= nil then
			local inputDesc = FruitUtil.fruitTypes[inputType];
			if inputDesc ~= nil then
				self.fruitTypes[inputDesc.index] = true;
				self.fruitOutputTypes[inputDesc.index] = outputTypeDesc;
			end;
		end;
		i = i + 1;
	end;
	self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
	
	self.psEnabled = false;
end;

function E302_Cutter:delete()
    if self.mowerSound ~= nil then
        delete(self.mowerSound);
    end;
	for k, cutterParticleSystem in pairs(self.cutterParticleSystems) do
		Utils.deleteParticleSystem(cutterParticleSystem.particleSystem, false);
	end;
	for k, dustParticleSystem in pairs(self.dustParticleSystems) do
		Utils.deleteParticleSystem(dustParticleSystem.particleSystem, false);
	end;
end;

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

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

function E302_Cutter:update(dt)
    if self:getIsActiveForInput() then
		if self.attacherVehicle ~= nil and self.attacherVehicle.isMotorStarted then
			if InputBinding.hasEvent(InputBinding.ACTIVATE_THRESHING) then
				self:setIsTurnedOn(not self.isTurnedOn);
			end;
		end;
    end;
	if self.isTurnedOn then
		for _, rollNode in pairs(self.extraRollNodes) do
			rotate(rollNode.node, -dt*rollNode.speed.x, -dt*rollNode.speed.y, -dt*rollNode.speed.z);
		end;
		if self.reelNode ~= nil then
			rotate(self.reelNode, -dt*0.005, 0, 0);
			local atx, aty, atz = getRotation(self.reelNode);
			for i=1, self.spikesCount do
				local spike = getChildAt(self.spikesRootNode, i-1);
				--local tx, ty, tz = getRotation(spike);
				setRotation(spike, -atx, aty, atz);
			end;
		end;
		if self.isClient and self:getIsActiveForSound() 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;
	else
		if self.isClient and self:getIsActiveForSound() then
			if self.mowerSoundEnabled then
				stopSample(self.mowerSound);
				self.mowerSoundEnabled = false;
			end;
		end;
	end;
	
	--local cuttingAreasSend = {};
	self.wasToFast = false;
	self.psEnabled = false;

	if self:getIsActive() then
		if self.isTurnedOn then
			local hasGroundContact = false;
			local x,y,z = getWorldTranslation(self.groundReferenceNode);
			local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
			if terrainHeight+self.groundReferenceThreshold >= y then
				hasGroundContact = true;
			end;
			
			local fruitArea = 0;
			local grassArea = 0;
			
			if hasGroundContact then
				local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 21;
				if not toFast then
					local windrowerCuttingAreasSend = {};
					local windrowerDropAreasSend = {};

					for k,area in pairs(self.cuttingAreas) do
						for fruitType,v in pairs(self.fruitTypes) do
							if fruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then
								if self.currentFruitType == fruitType or self.currentFruitType == FruitUtil.FRUITTYPE_UNKNOWN then
									local x,y,z = getWorldTranslation(area.start);
									local x1,y1,z1 = getWorldTranslation(area.width);
									local x2,y2,z2 = getWorldTranslation(area.height);
									--table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
									
									if fruitType == FruitUtil.FRUITTYPE_GRASS then
										grassArea = Utils.updateMeadowArea(x, z, x1, z1, x2, z2);
										grassArea = grassArea + Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
										grassArea = grassArea + Utils.getFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0);
										grassArea = grassArea + Utils.getFruitWindrowArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, 0);
										grassArea = grassArea + Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, 0);
										
										local windrowerCuttingArea = self.windrowerCuttingAreas[1];									
										local wx,wy,wz = getWorldTranslation(windrowerCuttingArea.start);
										local wx1,wy1,wz1 = getWorldTranslation(windrowerCuttingArea.width);
										local wx2,wy2,wz2 = getWorldTranslation(windrowerCuttingArea.height);
										table.insert(windrowerCuttingAreasSend, {wx, wz, wx1, wz1, wx2, wz2});	
										
										local dropArea = self.windrowerDropAreas[1];									
										local dx,dy,dz = getWorldTranslation(dropArea.start);
										local dx1,dy1,dz1 = getWorldTranslation(dropArea.width);
										local dx2,dy2,dz2 = getWorldTranslation(dropArea.height);
										table.insert(windrowerDropAreasSend, {dx, dz, dx1, dz1, dx2, dz2});
										if self.isServer then
											if (table.getn(windrowerCuttingAreasSend) > 0) then
												local windrowerCuttingAreasSend, dropAreasSend, fruitType, bitType = WindrowAreaEvent.runLocally(windrowerCuttingAreasSend, windrowerDropAreasSend, self.accumulatedCuttingAreaValues);
												if table.getn(windrowerCuttingAreasSend) > 0 then
													g_server:broadcastEvent(WindrowAreaEvent:new(windrowerCuttingAreasSend, dropAreasSend, fruitType, bitType));
												end;
											end;
										end;
									else
										fruitArea = Utils.getFruitArea(fruitType, x, z, x1, z1, x2, z2);
										fruitArea = fruitArea + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0);
										fruitArea = fruitArea + Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0);
									end;
									
									if fruitArea > 0 then
										self.currentFruitType = fruitType;
										Utils.updateFruitCutShortArea(fruitType, x, z, x1, z1, x2, z2, 1);
										Utils.cutFruitArea(fruitType, x, z, x1, z1, x2, z2);
										
										local dropArea = self.windrowerDropAreas[1];
										x,y,z = getWorldTranslation(dropArea.start);
										x1,y1,z1 = getWorldTranslation(dropArea.width);
										x2,y2,z2 = getWorldTranslation(dropArea.height);
										
										if self.fruitOutputTypes[fruitType] == "cut_long" then
											old, total = Utils.getFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2);
										elseif self.fruitOutputTypes[fruitType] == "windrow" then
											old, total = Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2);
										end;

										local value = 1 + math.floor(old / total + 0.7);
										value = math.min(value, g_currentMission.maxWindrowValue);
										
										if self.fruitOutputTypes[fruitType] == "cut_long" then
											Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, value, true);
										elseif self.fruitOutputTypes[fruitType] == "windrow" then
											Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, value, true);	
										end;
										self.psEnabled = true;
									elseif grassArea > 0 then
										self.currentFruitType = fruitType;
										self.psEnabled = true;
									end;
								end;
							end;
						end;
					end;
				else
					self.psEnabled = false;
				end;
				self.wasToFast = toFast;
			else
				self.psEnabled = false;
			end;
		else
			self.psEnabled = false;
		end;
	end;

	for k, cutterParticleSystem in pairs(self.cutterParticleSystems) do
		if k == self.currentFruitType then
			Utils.setEmittingState(cutterParticleSystem.particleSystem, self.psEnabled);
		else
			Utils.setEmittingState(cutterParticleSystem.particleSystem, false);
		end;
	end;
	
	for k, dustParticleSystem in pairs(self.dustParticleSystems) do
		if k == self.currentFruitType then
			Utils.setEmittingState(dustParticleSystem.particleSystem, self.psEnabled);
		else
			Utils.setEmittingState(dustParticleSystem.particleSystem, false);
		end;
	end;
end;

function E302_Cutter:updateTick(dt)
end;

function E302_Cutter:draw()
	if self.isClient then
		if self.attacherVehicle ~= nil and self.attacherVehicle.isMotorStarted then
			if self.isTurnedOn then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.ACTIVATE_THRESHING);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.ACTIVATE_THRESHING);
			end;
		end;
		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;
		if self.currentFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then
			g_currentMission:setFruitOverlayFruitType(self.currentFruitType);
		end;
	end;
end;

function E302_Cutter:onDetach()
    if self.deactivateOnDetach then
        E302_Cutter.onDeactivate(self);
    else
        E302_Cutter.onDeactivateSounds(self)
    end;
end;

function E302_Cutter:onLeave()
    if self.deactivateOnLeave then
        E302_Cutter.onDeactivate(self);
    else
        E302_Cutter.onDeactivateSounds(self)
    end;
end;

function E302_Cutter:onDeactivate()
    E302_Cutter.onDeactivateSounds(self)
    self.isTurnedOn = false;
	for k, cutterParticleSystem in pairs(self.cutterParticleSystems) do
		Utils.setEmittingState(cutterParticleSystem.particleSystem, false);
	end;
end;

function E302_Cutter:onDeactivateSounds()
    if self.mowerSoundEnabled then
        stopSample(self.mowerSound);
        self.mowerSoundEnabled = false;
    end;
end;

function E302_Cutter:setIsTurnedOn(isTurnedOn, noEventSend)
	SetTurnedOnEvent.sendEvent(self, isTurnedOn, noEventSend)
	self.isTurnedOn = isTurnedOn;
	if isTurnedOn == false then
		self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
	end;
end;