--
-- fillSowingTrailer
--
-- @author:    	Xentro (www.fs-uk.com)(Marcus@Xentro.se)
-- @version:    v1.1
-- @date:       2013-04-04
-- 
--[[
<fillSowingTrailer trigger="" clip="" rootNode="" openSpeedScale="" closeSpeedScale="" dischargeStartTime="1" dischargeEndTime="10">
	<dischargeParticleSystem type="" node="" position="0 0 0" rotation="0 0 0" file="" />
</fillSowingTrailer>
]]--
-----------------------------------------------------------------------
-- edited by Henly20 nimodding
-- 04/07/2013
-- changed to stop tipping when not attached and allowable fill types to fill a sowing machine

fillSowingTrailer = {};

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

function fillSowingTrailer:load(xmlFile)
	self.setTipAnim = SpecializationUtil.callSpecializationsFunction("setTipAnim");
	self.sowingTriggerCallback = fillSowingTrailer.sowingTriggerCallback;
	self.fillSowingMachine = fillSowingTrailer.fillSowingMachine;
	self.getIsActivatable = fillSowingTrailer.getIsActivatable;
	self.setFillLevel = Utils.prependedFunction(self.setFillLevel, fillSowingTrailer.setFillLevel);
	self.getCurrentFillSowingAnimationTime = fillSowingTrailer.getCurrentFillSowingAnimationTime;
	
	self.fillTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillSowingTrailer#trigger"));
	if self.fillTrigger ~= nil then
		addTrigger(self.fillTrigger, "sowingTriggerCallback", self);
	end;
	self.allowfilling = false;	
	self.allowTipping = false;

	self.fillingSowingMachines = {};
	
	local animationNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillSowingTrailer#rootNode"));
	if animationNode ~= nil then
		local charSet = getAnimCharacterSet(animationNode);
		if charSet ~= nil then
			local clip = getAnimClipIndex(charSet, getXMLString(xmlFile, "vehicle.fillSowingTrailer#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.fillSowingTrailer#openSpeedScale"), 1);
				self.fillAnimation.closeSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillSowingTrailer#closeSpeedScale"), -1);
				self.fillAnimation.dischargeStartTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillSowingTrailer#dischargeStartTime"), 0)*1000;
				self.fillAnimation.dischargeEndTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillSowingTrailer#dischargeEndTime"), 5)*1000;
				self.fillAnimation.tipping = 0;
				
				local ip = 0;
				while true do
					local keyPS = string.format("vehicle.fillSowingTrailer.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();
    self.printWarningTime = 0;	
end;

function fillSowingTrailer: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 fillSowingTrailer:readStream(streamId, connection)
end;

function fillSowingTrailer:writeStream(streamId, connection)
end;

function fillSowingTrailer: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 fillSowingTrailer: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 fillSowingTrailer:mouseEvent(posX, posY, isDown, isUp, button)
end;

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

function fillSowingTrailer:update(dt)
end;

function fillSowingTrailer:updateTick(dt)
		if (self.currentFillType == Fillable.FILLTYPE_CHAFF or self.currentFillType == Fillable.FILLTYPE_MANURE or self.currentFillType == Fillable.FILLTYPE_SILAGE or self.currentFillType == Fillable.FILLTYPE_CHAFF or self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW) and self.currentTipReferencePointIndex == 2 then
            self:enableTipAnimation(false);

			if (Input.isKeyPressed(Input.KEY_lctrl) and Input.isKeyPressed(Input.KEY_q)) or Input.isKeyPressed(Input.KEY_q) then
				self.printWarningTime = self.time + 1000;		
			end;
		end;
	if self:getIsActive() or not self:getIsActive() then	
		for _, part in pairs(self.movingParts) do
			Cylindered.setDirty(self, part);
		end;

		for _, part in pairs(self.movingTools) do
			Cylindered.setDirty(self, part);
		end;	
	end		
	if self.allowTipping then
		if self.currentFillType == Fillable.FILLTYPE_CHAFF or self.currentFillType == Fillable.FILLTYPE_MANURE or self.currentFillType == Fillable.FILLTYPE_SILAGE then
			self.allowfilling = false;
		elseif self.currentFillType == Fillable.FILLTYPE_BARLEY or 	self.currentFillType == Fillable.FILLTYPE_WHEAT or self.currentFillType == Fillable.FILLTYPE_RAPE or self.currentFillType == Fillable.FILLTYPE_MAIZE or self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW or self.currentFillType == Fillable.FILLTYPE_SUGARBEET or self.currentFillType == Fillable.FILLTYPE_POTATO then
			self.allowfilling = true;
			self.seedType = Fillable.FILLTYPE_SEEDS;		
		end;

		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;
end;

function fillSowingTrailer:draw()
    if self.isClient then
		if self.printWarningTime > self.time then
			g_currentMission:addWarning(g_i18n:getText("Dump_Error"), 0.018, 0.033);
		end;
	end;
end;

function fillSowingTrailer:onAttach(attacherVehicle)
	self.allowTipping = true;

end;
function fillSowingTrailer:onDetach()
	self.allowTipping = false;
end;

function fillSowingTrailer: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 fillSowingTrailer:fillSowingMachine(sowingMachine, delta)
	if not sowingMachine:allowFillType(self.seedType, false) then
		return 0;
	end;
	if self.allowTipping then	
		if self.allowfilling then	
			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;
		end;
	end;

	return delta;
end;

function fillSowingTrailer: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 fillSowingTrailer:getCurrentFillSowingAnimationTime()
	if self.fillAnimation ~= nil and self.fillAnimation.charSet ~= nil then
		return getAnimTrackTime(self.fillAnimation.charSet, 0);
	end;
	
	return 0;
end;

function fillSowingTrailer:sowingTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	if self.allowTipping then	
		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;
end;

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