-- WheelTracks
-- Specialisation for Tracks by wheels
--
-- @ Autor  Tobias F. (John Deere 6930)
-- @ Last Edit  03/08/2011

WheelTracks = {};
function WheelTracks.prerequisitesPresent(specializations)
    return true;
end;

function WheelTracks:load(xmlFile)	
	self.wheelTrack = {};
	self.wheelTrack.dirtFileDry = Utils.convertToNetworkFilename(Utils.getFilename(getXMLString(xmlFile, "vehicle.wheelTrack#dirtFileDry"), self.baseDirectory));
	self.wheelTrack.dirtFileRain = Utils.convertToNetworkFilename(Utils.getFilename(getXMLString(xmlFile, "vehicle.wheelTrack#dirtFileRain"), self.baseDirectory));
	self.wheelTrack.minDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#minDistance"),0.1);
	self.cultivatorAndPloughUpdateValue = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#cultivatorAndPloughUpdateValue"),0.01);
	self.rainingUpdateMultiplicatorValue = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#rainingUpdateMultiplicatorValue"),1.25);
	self.sowingUpdateValue = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#sowingUpdateValue"),0.008);
	self.decreaseSpeedMultiplictor = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#decreaseSpeedMultiplictor"),2);
	self.maxDirtSpawnValue = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wheelTrack#maxDirtSpawnValue"),50);
	
	self.wheelTrackWarning_hud = Overlay:new("wheelTrackWarning_hud", Utils.getFilename("texture/wheelTrackWarning_hud.png", self.baseDirectory), 0.65, 0.02, 0.1, 0.1);	
	self.renderWheelTrackWarningTime = 0;
	
	function connectTables(tables, finalTable)
		for _, tab in pairs(tables) do
			for k, value in pairs(tab) do
				table.insert(finalTable, value);
			end;
		end;
	end;
	
	local tables = {};
		
	-- normal wheelTrack support
	tables[1] = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.wheelTrack.node(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#wheelTrackSpawn"));
		if nodei == nil then
			break;
		end; 
		local entry = {};
		entry.wheelTrackSpawn = nodei;
		entry.activTrack = true;
		entry.timeOnDirtGround = 0;
		entry.dustParticleSystem = {};
		Utils.loadParticleSystem(xmlFile, entry.dustParticleSystem, "vehicle.wheelTrack.dustParticleSystem", entry.wheelTrackSpawn, false, nil, self.baseDirectory);
		entry.clumpsParticleSystem = {};        
		Utils.loadParticleSystem(xmlFile, entry.clumpsParticleSystem, "vehicle.wheelTrack.clumpsParticleSystem", entry.wheelTrackSpawn, false, nil, self.baseDirectory);
		entry.createDirt = false;
		entry.lastCreatedGround = nil;
		entry.alphaValue = 0;
		table.insert(tables[1], entry);
		i = i+1;
    end;   
	
	-- supports the SwitchingNWheelModes Specialization
    if SpecializationUtil.hasSpecialization(SwitchingNWheelModes, self.specializations) then
		for k,v in pairs(self.wheelVisibility) do
			if v.wheelTrackSpawn ~= nil then
				v.dustParticleSystem = {};
				Utils.loadParticleSystem(xmlFile, v.dustParticleSystem, "vehicle.wheelTrack.dustParticleSystem", v.wheelTrackSpawn, false, nil, self.baseDirectory);
				v.clumpsParticleSystem = {};        
				Utils.loadParticleSystem(xmlFile, v.clumpsParticleSystem, "vehicle.wheelTrack.clumpsParticleSystem", v.wheelTrackSpawn, false, nil, self.baseDirectory);
				v.activTrack = false;
				v.timeOnDirtGround = 0;
				v.createDirt = false;
				v.lastCreatedGround = nil;
				v.alphaValue = 0;
			end;
		end;
		tables[2] = self.wheelVisibility;
	end;
	
	self.connectedTrackTable = {};
	connectTables(tables, self.connectedTrackTable)
	
	self.setEmittingStateDustParticleSystem = false;
	self.setEmittingStateClumpsParticleSystem = false;
	self.setEmittingStateDustParticleSystemBackUp = false;
	self.setEmittingStateClumpsParticleSystemBackUp = false;
end;

function WheelTracks:delete()
end;

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

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

function WheelTracks:readStream(streamId, connection)
	if MapDirtObjects ~= nil then
		for _, wheelTrack in pairs(self.connectedTrackTable) do
			wheelTrack.activTrack = streamReadBool(streamId);
			wheelTrack.timeOnDirtGround = streamReadFloat32(streamId);
		end;
	end;
end;

function WheelTracks:writeStream(streamId, connection)
	if MapDirtObjects ~= nil then
		for _, wheelTrack in pairs(self.connectedTrackTable) do
			streamWriteBool(streamId, wheelTrack.activTrack);
			streamWriteFloat32(streamId, wheelTrack.timeOnDirtGround);
		end;
	end;
end;

function WheelTracks:updateTick(dt)
	if MapDirtObjects ~= nil then
		if self:getIsActive() then
			for k, wheelTrack in pairs(self.connectedTrackTable) do
				if wheelTrack.activTrack then
					local x,y,z = getWorldTranslation(wheelTrack.wheelTrackSpawn);
					local cultivatorChannel = Utils.getDensity(g_currentMission.terrainDetailId, g_currentMission.cultivatorChannel, x, z, x+0.01, z, x, z+0.01);
					local ploughChannel = Utils.getDensity(g_currentMission.terrainDetailId, g_currentMission.ploughChannel, x, z, x+0.01, z, x, z+0.01);
					local sowingChannel = Utils.getDensity(g_currentMission.terrainDetailId, g_currentMission.sowingChannel, x, z, x+0.01, z, x, z+0.01);
					if self.isServer then
						--checks if vehicle is on editable ground
						if cultivatorChannel>0 or ploughChannel>0 or sowingChannel>0 then
							if self.movingDirection ~= 0 then
								if wheelTrack.timeOnDirtGround < self.maxDirtSpawnValue then
									--updates time on dirt ground time
									local updateValue = 0;
									if cultivatorChannel>0 or ploughChannel>0 then
										updateValue = self.cultivatorAndPloughUpdateValue;
										if g_currentMission.environment.lastRainScale > 0.1 and g_currentMission.environment.timeSinceLastRain < 30 then
											updateValue = updateValue*self.rainingUpdateMultiplicatorValue;
										end;
									elseif sowingChannel>0 then
										updateValue = self.sowingUpdateValue;	
										if g_currentMission.environment.lastRainScale > 0.1 and g_currentMission.environment.timeSinceLastRain < 30 then
											updateValue = updateValue*self.rainingUpdateMultiplicatorValue;
										end;				
									end;						
									--adding timeOnGround
									wheelTrack.timeOnDirtGround = wheelTrack.timeOnDirtGround + updateValue;	
								end;
							end;
						else
							--vehicle isn't on ground, but is able to create dirt
							if wheelTrack.timeOnDirtGround > 0 and self.movingDirection ~= 0 then
								--creatingDirt
								if wheelTrack.timeOnDirtGround >= 0.15 and self.lastSpeed*3600 > 8 then
									if wheelTrack.lastCreatedGround == nil then
										--createDirt!
										wheelTrack.createDirt = true;
									else
										local px, py, pz = getWorldTranslation(wheelTrack.wheelTrackSpawn);
										local vx, vy, vz = unpack(wheelTrack.lastCreatedGround);
										wheelTrack.distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
										if wheelTrack.distance > self.wheelTrack.minDistance then
											--createDirt!
											wheelTrack.createDirt = true;
										end;
									end;
									local percent = wheelTrack.timeOnDirtGround/self.maxDirtSpawnValue						
									if percent >= 0.2 then
										wheelTrack.alphaValue = percent;
									else
										wheelTrack.timeOnDirtGround = 0;
										wheelTrack.alphaValue = 0;
									end;
									--decrease timeOnGround
									wheelTrack.timeOnDirtGround = wheelTrack.timeOnDirtGround-self.lastSpeed*self.decreaseSpeedMultiplictor;
								end;
							end;
						end;						
						if wheelTrack.createDirt then
							if wheelTrack.alphaValue >= 0.2 then
								local filename;
								if g_currentMission.environment.lastRainScale > 0.1 and g_currentMission.environment.timeSinceLastRain < 30 then
									filename = self.wheelTrack.dirtFileRain;
								else
									filename = self.wheelTrack.dirtFileDry;
								end;
								if filename ~= nil then
									self.renderWheelTrackWarningTime = self.time+500;
									local rx, ry, rz = getWorldRotation(wheelTrack.wheelTrackSpawn);
									local tx, ty, tz = getWorldTranslation(wheelTrack.wheelTrackSpawn);
									MapDirtObjects.MapDirtObjects:createNewDirtObject(filename, tx, ty, tz, rx, ry, rz, wheelTrack.alphaValue)
									g_server:broadcastEvent(MapDirtObjects.CreateNewDirtObjectEvent:new(filename, tx, ty, tz, rx, ry, rz, wheelTrack.alphaValue), nil, nil, self);
									wheelTrack.lastCreatedGround = {tx, ty, tz}
									wheelTrack.createDirt = false;
								else
									print("Error - i3d filename of wheelTrack is nil - "..self.name)
								end;
							else
								wheelTrack.createDirt = false;
							end;
						end;
					end;
					if wheelTrack.timeOnDirtGround > 0 and self.movingDirection ~= 0 then
						if g_currentMission.environment.lastRainScale > 0.1 and g_currentMission.environment.timeSinceLastRain < 30 then
							if cultivatorChannel>0 or ploughChannel>0 or sowingChannel>0 then
								if self.lastSpeed*3600 > 20 then
									if cultivatorChannel>0 or ploughChannel>0 then
										self.setEmittingStateDustParticleSystem = false;
										self.setEmittingStateClumpsParticleSystem = true;									
									else
										self.setEmittingStateDustParticleSystem = false;
										self.setEmittingStateClumpsParticleSystem = false;	
									end;
								end;
							else
								if self.lastSpeed*3600 > 16 then
									self.setEmittingStateDustParticleSystem = true;
									self.setEmittingStateClumpsParticleSystem = true;
								end;						
							end;
						else
							if cultivatorChannel>0 or ploughChannel>0 or sowingChannel>0 then
								if self.lastSpeed*3600 > 20 then
									if cultivatorChannel>0 or ploughChannel>0 then
										self.setEmittingStateDustParticleSystem = true;
										self.setEmittingStateClumpsParticleSystem = true;									
									else
										self.setEmittingStateDustParticleSystem = true;
										self.setEmittingStateClumpsParticleSystem = false;	
									end;
								end;
							else
								if self.lastSpeed*3600 > 16 then
									self.setEmittingStateDustParticleSystem = true;
									self.setEmittingStateClumpsParticleSystem = true;
								end;						
							end;
						end;
					else
						self.setEmittingStateDustParticleSystem = false;
						self.setEmittingStateClumpsParticleSystem = false;
					end;
					if self.lastSpeed*3600 < 16 then
						self.setEmittingStateDustParticleSystem = false;
						self.setEmittingStateClumpsParticleSystem = false;
					end;
				end;
			end;
		else
			self.setEmittingStateDustParticleSystem = false;
			self.setEmittingStateClumpsParticleSystem = false;
		end;
		
		if self.setEmittingStateDustParticleSystem ~= self.setEmittingStateDustParticleSystemBackUp then
			for k, wheelTrack in pairs(self.connectedTrackTable) do
				Utils.setEmittingState(wheelTrack.dustParticleSystem, self.setEmittingStateDustParticleSystem);
			end;
			self.setEmittingStateDustParticleSystemBackUp = self.setEmittingStateDustParticleSystem;
		end;
		if self.setEmittingStateClumpsParticleSystem ~= self.setEmittingStateClumpsParticleSystemBackUp then
			for k, wheelTrack in pairs(self.connectedTrackTable) do
				Utils.setEmittingState(wheelTrack.clumpsParticleSystem, self.setEmittingStateClumpsParticleSystem);
			end;
			self.setEmittingStateClumpsParticleSystemBackUp = self.setEmittingStateClumpsParticleSystem;
		end;
	end;
end;

function WheelTracks:update(dt)
	if not self.updatedI3dPaths then
		if MapDirtObjects ~= nil then
		
		else
			print("Error: MapDirtObjects was not founded in modsfolder or isn't selected in mp-screen! WheelTracks are disabled!");
		end;
		self.updatedI3dPaths = true;
	end;
end;

function WheelTracks:draw()
	if self.renderWheelTrackWarningTime >= self.time then
		self.wheelTrackWarning_hud:render();
	end;
end;