--
-- fillTrailer
--
-- @author:    	Xentro (www.fs-uk.com)(Marcus@Xentro.se)
-- @version:    v1.1
-- @date:       2013-04-04
-- 
--[[
<fillTrailer trigger="" clip="" rootNode="" openSpeedScale="" closeSpeedScale="" dischargeStartTime="1" dischargeEndTime="10">
	<dischargeParticleSystem type="" node="" position="0 0 0" rotation="0 0 0" file="" />
</fillTrailer>
]]--

fillTrailer = {};

function fillTrailer.prerequisitesPresent(specializations)
	if not SpecializationUtil.hasSpecialization(Fillable, specializations) then print("Warning: Specialization fillTrailer needs the specialization Fillable."); end;
	
	return SpecializationUtil.hasSpecialization(Fillable, specializations);
end;

function fillTrailer:load(xmlFile)
	self.setTipAnim = SpecializationUtil.callSpecializationsFunction("setTipAnim");
	self.sowingTriggerCallback = fillTrailer.sowingTriggerCallback;
	self.fillSowingMachine = fillTrailer.fillSowingMachine;
	self.getIsActivatable = fillTrailer.getIsActivatable;
	self.setFillLevel = Utils.prependedFunction(self.setFillLevel, fillTrailer.setFillLevel);
	self.getCurrentFillSowingAnimationTime = fillTrailer.getCurrentFillSowingAnimationTime;
	
	self.fillTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillTrailer#trigger"));
	if self.fillTrigger ~= nil then
		addTrigger(self.fillTrigger, "sowingTriggerCallback", self);
	end;
	
	self.seedType = Fillable.FILLTYPE_SEEDS;
	self.fillingSowingMachines = {};
	
	local animationNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillTrailer#rootNode"));
	if animationNode ~= nil then
		local charSet = getAnimCharacterSet(animationNode);
		if charSet ~= nil then
			local clip = getAnimClipIndex(charSet, getXMLString(xmlFile, "vehicle.fillTrailer#clip"));
			if clip ~= nil then
				assignAnimTrackClip(charSet, 0, clip);
				setAnimTrackLoopState(charSet, 0, false);
				
				self.fillAnimation = {};
				self.fillAnimation.charSet = charSet;
				self.fillAnimation.duration = getAnimClipDuration(charSet, clip);
				self.fillAnimation.openSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillTrailer#openSpeedScale"), 1);
				self.fillAnimation.closeSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillTrailer#closeSpeedScale"), -1);
				self.fillAnimation.dischargeStartTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillTrailer#dischargeStartTime"), 0)*1000;
				self.fillAnimation.dischargeEndTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillTrailer#dischargeEndTime"), 5)*1000;
				self.fillAnimation.tipping = 0;
				
				local ip = 0;
				while true do
					local keyPS = string.format("vehicle.fillTrailer.dischargeParticleSystem(%d)", ip);
					local t = getXMLString(xmlFile, keyPS .. "#type");
					if t == nil then break; end;
					
					local fillType = Fillable.fillTypeNameToInt[t];
					if fillType ~= nil then
						local currentPS = {};
						local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, keyPS, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
						
						if self.fillAnimation.dischargeParticleSystems == nil then
							self.fillAnimation.dischargeParticleSystems = {};
						end;
						self.fillAnimation.dischargeParticleSystems[fillType] = currentPS;
					end;
					ip = ip + 1;
				end;
			end;
		end;
	end;
	
	self.fillSowingTrailerDirtyFlag = self:getNextDirtyFlag();
end;

function fillTrailer:delete()
	if self.fillTrigger ~= nil then
		removeTrigger(self.fillTrigger);
	end;
	
	if self.fillAnimation.dischargeParticleSystems ~= nil then
		for _, particleSystem in pairs(self.fillAnimation.dischargeParticleSystems) do
			Utils.deleteParticleSystem(particleSystem);
		end;
	end;
end;

function fillTrailer:readStream(streamId, connection)
end;

function fillTrailer:writeStream(streamId, connection)
end;

function fillTrailer:readUpdateStream(streamId, timestamp, connection)
	if connection:getIsServer() then
		if streamReadBool(streamId) then
			local tipState = streamReadInt8(streamId);
			
			local animFillTime = streamReadFloat32(streamId);
			if self.fillAnimation.charSet ~= nil then
				setAnimTrackTime(self.fillAnimation.charSet, 0, animFillTime);
			end;
			
			self:setTipAnim(tipState);
			
			local tempSowingMachine = streamReadInt32(streamId);
			if tempSowingMachine ~= 0 then
				self.tempSowingMachine = networkGetObject(tempSowingMachine);
			else
				self.tempSowingMachine = nil;
			end;
		end;
	end;
end;

function fillTrailer:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection:getIsServer() then
		if streamWriteBool(streamId, bitAND(dirtyMask, self.fillSowingTrailerDirtyFlag) ~= 0) then
			streamWriteInt8(streamId, self.fillAnimation.tipping);
			
			local animFillTime = self:getCurrentFillSowingAnimationTime();
			streamWriteFloat32(streamId, animFillTime);
			
			local tempSowingMachine = 0;
			if self.tempSowingMachine ~= nil then
				tempSowingMachine = networkGetObjectId(self.tempSowingMachine);
			end;
			streamWriteInt32(streamId, tempSowingMachine)
		end;
	end;
end;

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

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

function fillTrailer:update(dt)
end;

function fillTrailer:updateTick(dt)
	if self.fillAnimation ~= nil then
		if self.isServer then
			if self.fillAnimation.tipping ~= 0 then
				local trackTime = getAnimTrackTime(self.fillAnimation.charSet, 0);
				
				if trackTime < 0 or trackTime > self.fillAnimation.duration then
					self:setTipAnim(0);
				end;
			end;
			
			if self.tempSowingMachine ~= nil then
				if not self.tempSowingMachine.isSowingMachineFilling and self.fillAnimation.tipping >= 0 then
					self.tempSowingMachine = nil;
					self:setTipAnim(self.fillAnimation.closeSpeedScale);
				end;
			end;
		end;
		
		if self.fillAnimation.dischargeParticleSystems ~= nil and self.fillAnimation.dischargeParticleSystems[self.currentFillType] ~= nil then
			if self.tempSowingMachine ~= nil and self.fillAnimation.tipping == 1 and self.fillLevel > 0 and self:getCurrentFillSowingAnimationTime() >= self.fillAnimation.dischargeStartTime then
				Utils.setEmittingState(self.fillAnimation.dischargeParticleSystems[self.currentFillType], true);
			else
				Utils.setEmittingState(self.fillAnimation.dischargeParticleSystems[self.currentFillType], false);
			end;
		end;
	end;
end;

function fillTrailer:draw()
end;

function fillTrailer:setTipAnim(speedScale)
	if speedScale ~= 0 then
		local trackTime = math.max(0, getAnimTrackTime(self.fillAnimation.charSet, 0));
		if speedScale < 0 then
			trackTime = math.min(self.fillAnimation.duration, trackTime);
		end;
		
		setAnimTrackTime(self.fillAnimation.charSet, 0, trackTime);
		setAnimTrackSpeedScale(self.fillAnimation.charSet, 0, speedScale);
		enableAnimTrack(self.fillAnimation.charSet, 0);
	else
		disableAnimTrack(self.fillAnimation.charSet, 0);
	end;
	
	self.fillAnimation.tipping = speedScale;
	self:raiseDirtyFlags(self.fillSowingTrailerDirtyFlag);
end;

function fillTrailer:fillSowingMachine(sowingMachine, delta)
	if not sowingMachine:allowFillType(self.seedType, false) then
		return 0;
	end;
	
	local oldFillLevel = sowingMachine:getFillLevel(self.currentFillType);
	local trailer = self.fillLevel;
	delta = math.min(delta, trailer);
	
	if self.fillAnimation ~= nil then
		if self.fillAnimation.dischargeEndTime > self.fillAnimation.dischargeStartTime then			
			if delta > 0 then
				self.tempSowingMachine = sowingMachine;
				
				if self.fillAnimation.tipping == 0 then
					self:setTipAnim(self.fillAnimation.openSpeedScale);
				end;
			else
				if self.fillAnimation.tipping == 0 or self.fillAnimation.tipping > 0 then
					self:setTipAnim(self.fillAnimation.closeSpeedScale);
				end;
			end;
			
			if self:getCurrentFillSowingAnimationTime() >= self.fillAnimation.dischargeStartTime then
				if delta > 0 then
					sowingMachine:setFillLevel(oldFillLevel + delta, self.seedType, true);
					delta = sowingMachine:getFillLevel(self.seedType) - oldFillLevel;
					
					self:setFillLevel(trailer - delta, self.currentFillType);
				end;
			end;
		end;
	end;
	
	return delta;
end;


function fillTrailer:setFillLevel(fillLevel, fillType, force)
	if self.isClient then
		if (self.currentFillType ~= fillType or fillLevel <= 0) then
			if self.fillAnimation ~= nil and self.fillAnimation.dischargeParticleSystems ~= nil and self.fillAnimation.dischargeParticleSystems[self.currentFillType] ~= nil then
				Utils.setEmittingState(self.fillAnimation.dischargeParticleSystems[self.currentFillType], false);
			end;
		end;
	end;
end;

function fillTrailer:getCurrentFillSowingAnimationTime()
	if self.fillAnimation ~= nil and self.fillAnimation.charSet ~= nil then
		return getAnimTrackTime(self.fillAnimation.charSet, 0);
	end;
	
	return 0;
end;

function fillTrailer:sowingTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	local sowingMachine = g_currentMission.objectToTrailer[otherShapeId];

	if sowingMachine ~= nil and sowingMachine.addSowingMachineFillTrigger ~= nil and sowingMachine.removeSowingMachineFillTrigger ~= nil then
		if self.fillLevel ~= 0 and onEnter then
			if self.fillingSowingMachines[sowingMachine] == nil then
				sowingMachine:addSowingMachineFillTrigger(self);
				self.fillingSowingMachines[sowingMachine] = true;
			end;
		elseif self.fillLevel == 0 or onLeave then
			if self.fillingSowingMachines[sowingMachine] ~= nil then
				sowingMachine:removeSowingMachineFillTrigger(self);
				self.fillingSowingMachines[sowingMachine] = nil;
			end;
		end;
	end;
end;

function fillTrailer:getIsActivatable(fillable)
	if not fillable:allowFillType(self.seedType, false) or self.fillLevel == 0 then
		return false;
	end;
	
	return true;
end;