-- LemkenVariopack
-- Specialization for LemkenVariopack
--
--
--
--
--


LemkenVariopack = {};

function LemkenVariopack.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Attachable, specializations);
end;

function LemkenVariopack:load(xmlFile)
		
	--
	self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.2);
	self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
		
	--
	self.speedRotatingParts = {};
	local i=0;
	while true do
		local baseName = string.format("vehicle.speedRotatingParts.speedRotatingPart(%d)", i);
		local index = getXMLString(xmlFile, baseName.. "#index");
		if index == nil then
			break;
		end;
		local node = Utils.indexToObject(self.components, index);
		if node ~= nil then
			local entry = {};
			entry.node = node;
			entry.rotationSpeedScale = getXMLFloat(xmlFile, baseName.."#rotationSpeedScale");
			if entry.rotationSpeedScale == nil then
			   entry.rotationSpeedScale = 1.0/Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#radius"), 1);
			end;

			entry.rotateOnGroundContact = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#rotateOnGroundContact"), false);

			entry.foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#foldMinLimit"), 0);
			entry.foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#foldMaxLimit"), 1);

			table.insert(self.speedRotatingParts, entry);
		end;
		i = i+1;
	end	
	
	self.hasGroundContact = false;
	self.setGroundContactInfo = SpecializationUtil.callSpecializationsFunction("setGroundContactInfo"); 
	
	
	--#
	local cultivatorSound = getXMLString(xmlFile, "vehicle.cultivatorSound#file");
	self.cultivatorSoundEnabled = false;
	if cultivatorSound ~= nil and cultivatorSound ~= "" then
		cultivatorSound = Utils.getFilename(cultivatorSound, self.baseDirectory);
		self.cultivatorSound = createSample("cultivatorSound");
		loadSample(self.cultivatorSound, cultivatorSound, false);
		self.cultivatorSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cultivatorSound#pitchOffset"), 0);
		self.cultivatorSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cultivatorSound#volume"), 1.0);
		setSamplePitch(self.cultivatorSound, self.cultivatorSoundPitchOffset);
	end	
	
	self.groundParticleSystems = {};
	local entry = {};
	entry.ps = {};
	Utils.loadParticleSystem(xmlFile, entry.ps, "vehicle.groundParticleSystem", self.components, false, nil, self.baseDirectory);
	if table.getn(entry.ps) > 0 then
		entry.isActive = false;
		table.insert(self.groundParticleSystems, entry);
	end
	local i=0;
	while true do
		local baseName = string.format("vehicle.groundParticleSystems.groundParticleSystem(%d)", i);
		if not hasXMLProperty(xmlFile, baseName) then
			break;
		end;
		local entry = {};
		entry.ps = {};
		Utils.loadParticleSystem(xmlFile, entry.ps, baseName, self.components, false, nil, self.baseDirectory);
		if table.getn(entry.ps) > 0 then
		entry.isActive = false;
		entry.cuttingArea = i+1;
		table.insert(self.groundParticleSystems, entry);
		end
		i = i+1;
	end;	
	
end;

function LemkenVariopack:delete()
	for _, entry in ipairs(self.groundParticleSystems) do
		Utils.deleteParticleSystem(entry.ps);
		entry.isActive = false;
	end;

	if self.cultivatorSound ~= nil then
		delete(self.cultivatorSound);
		self.cultivatorSoundEnabled = false;
	end;
end;

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

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

function LemkenVariopack:update(dt)
end;

function LemkenVariopack:updateTick(dt)
	
	if self:getIsActive() then
		if self.isServer then
			local hasGroundContact = false;
			if self.groundReferenceNode ~= nil then
				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;
			end;		
			if hasGroundContact ~= self.hasGroundContact then
				self:setGroundContactInfo(hasGroundContact);
			end;

			if hasGroundContact then
				local cuttingAreasSend = {};
				for k,cuttingArea in pairs(self.cuttingAreas) do
					if self:getIsAreaActive(cuttingArea) then
						local x,y,z = getWorldTranslation(cuttingArea.start);
						local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
						local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
						table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
					end;
				end;
				if (table.getn(cuttingAreasSend) > 0) then
					local limitToField = true;
					local limitGrassDestructionToField = true;
					
					local dx,dy,dz = localDirectionToWorld(self.components[1].node, 0, 0, 1);
					local angle = Utils.convertToDensityMapAngle(Utils.getYRotationFromDirection(dx, dz), g_currentMission.terrainDetailAngleMaxValue);
					
					local realArea = CultivatorAreaEvent.runLocally(cuttingAreasSend, limitToField, limitGrassDestructionToField, angle);
					g_server:broadcastEvent(CultivatorAreaEvent:new(cuttingAreasSend, limitToField, limitGrassDestructionToField, angle));				
				end;

			end;
		
		end;
		
		if self.isClient then
			for _,ps in pairs(self.groundParticleSystems) do
				local enabled = (self.hasGroundContact and self.lastSpeed*3600 > 5)
				if enabled and ps.cuttingArea ~= nil and self.cuttingAreas[ps.cuttingArea] ~= nil then
					enabled = self:getIsAreaActive(self.cuttingAreas[ps.cuttingArea]);
				end
				if ps.isActive ~= enabled then
					ps.isActive = enabled;
					Utils.setEmittingState(ps.ps, ps.isActive);
				end
			end

			if self.cultivatorSound ~= nil then
				if self.hasGroundContact and self.lastSpeed*3600 > 3 then
					if not self.cultivatorSoundEnabled and self:getIsActiveForSound() then
						playSample(self.cultivatorSound, 0, self.cultivatorSoundVolume, 0);
						self.cultivatorSoundEnabled = true;
					end;
				else
					if self.cultivatorSoundEnabled then
						stopSample(self.cultivatorSound);
						self.cultivatorSoundEnabled = false;
					end;
				end;
			end;		
			if self.hasGroundContact then
				for k,v in pairs(self.speedRotatingParts) do
					rotate(v.node, v.rotationSpeedScale * self.lastSpeedReal * self.movingDirection * dt, 0, 0);
				end;
			end;
		end;
			
	end;
end;

function LemkenVariopack:draw()
end;

function LemkenVariopack:onAttach(attacherVehicle)

end;

function LemkenVariopack:onDetach()
end;

function LemkenVariopack:onLeave()
end;

function LemkenVariopack:setGroundContactInfo(state, noEventSend)
	SetGroundContactInformation.sendEvent(self, state, noEventSend);
	self.hasGroundContact = state;
end;


--
--
--
--
--
SetGroundContactInformation = {};
SetGroundContactInformation_mt = Class(SetGroundContactInformation, Event);

InitEventClass(SetGroundContactInformation, "SetGroundContactInformation");

function SetGroundContactInformation:emptyNew()
    local self = Event:new(SetGroundContactInformation_mt);
    self.className="SetGroundContactInformation";
    return self;
end;

function SetGroundContactInformation:new(vehicle, state)
    local self = SetGroundContactInformation:emptyNew()
    self.vehicle = vehicle;
	self.state = state;
	return self;
end;

function SetGroundContactInformation:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
	self.state = streamReadBool(streamId);
    self:run(connection);
end;

function SetGroundContactInformation:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteBool(streamId, self.state);
end;

function SetGroundContactInformation:run(connection)
	self.vehicle:setGroundContactInfo(self.state, true);
	if not connection:getIsServer() then				
		g_server:broadcastEvent(SetGroundContactInformation:new(self.vehicle, self.state), nil, connection, self.vehicle);
	end;
end;


function SetGroundContactInformation.sendEvent(vehicle, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetGroundContactInformation:new(vehicle, state), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetGroundContactInformation:new(vehicle, state));
		end;
	end;
end;






