--
-- GaluchoTipMode
-- Class for 3 sides tipping of Galucho trailers
--
-- @author  PeterJ  - euroDZN
-- @date  07/06/2012
--
-- http://eurodzn.wordpress.com/
--
-- Copyright (C) euroDZN, Confidential, All Rights Reserved.
  
GaluchoTipMode = {};

function GaluchoTipMode.prerequisitesPresent(specializations)
	return SpecializationUtil.hasSpecialization(Trailer, specializations) and SpecializationUtil.hasSpecialization(VariableBody, specializations);
end;
  
function GaluchoTipMode:load(xmlFile)

	self.setFillLevel = Utils.prependedFunction(self.setFillLevel, GaluchoTipMode.setFillLevel);
	self.enableTipAnimation = SpecializationUtil.callSpecializationsFunction("enableTipAnimation");
	
	self.setTipMode = SpecializationUtil.callSpecializationsFunction("setTipMode");
	self.setLiftBox = SpecializationUtil.callSpecializationsFunction("setLiftBox");
	self.tipMode = 1;
	self.numTipAnims = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims#numTipAnims"), 1);
	if self.numTipAnims > 3 then
		self.numTipAnims = 3;
	end;
	local backAnimIdx = getXMLInt(xmlFile, "vehicle.selectAbleTipAnims#backAnimIdx");
	if backAnimIdx ~= nil then
		self.backAnimIdx = backAnimIdx;
	else
		self.backAnimIdx = self.tipMode;
	end;

	self.tippingRef = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipReferencePoints.tipReferencePoint#index"));
  
	--- tip back animation ---
	self.tipAnimation1 = getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim1#animationName");
	local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim1#tipRefPosition"));
	self.refAnim1X = x;
	self.refAnim1Y = y;
	self.refAnim1Z = z;
	
	self.dischargeEndTime1 = getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim1#dischargeEndTime");
	if self.dischargeEndTime1 ~= nil then
		self.dischargeEndTime1 = self.dischargeEndTime1 * 1000;
	end;
	self.dischargeStartTime1 = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim1#dischargeStartTime"), 0)*1000;
	if self.isClient then
		self.dischargePartSystems1 = {};
		local i = 0;
		while true do
			local key = string.format("vehicle.selectAbleTipAnims.selectAbleTipAnim1.dischargeParticleSystems.dischargeParticleSystem(%d)", i);
			local t = getXMLString(xmlFile, key .. "#type");
			if t == nil then
				break;
			end;
			local desc = FruitUtil.fruitTypes[t];
			if desc ~= nil then
				local fillType = FruitUtil.fruitTypeToFillType[desc.index];
				local currentPS = {};
  
				local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
				self.dischargePartSystems1[fillType] = currentPS;
				if self.defaultdischargeParticleSystems == nil then
					self.defaultdischargeParticleSystems = currentPS;
				end;
			end;
			i = i + 1;
		end;
	end;
	
	--- tip left animation ---
	self.tipAnimation2 = getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim2#animationName");
	local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim2#tipRefPosition"));
	self.refAnim2X = x;
	self.refAnim2Y = y;
	self.refAnim2Z = z;
	
	self.dischargeEndTime2 = getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim2#dischargeEndTime");
	if self.dischargeEndTime2 ~= nil then
		self.dischargeEndTime2 = self.dischargeEndTime2 * 1000;
	end;
	self.dischargeStartTime2 = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim2#dischargeStartTime"), 0)*1000;
	if self.isClient then
		self.dischargePartSystems2 = {};
		local i = 0;
		while true do
			local key = string.format("vehicle.selectAbleTipAnims.selectAbleTipAnim2.dischargeParticleSystems.dischargeParticleSystem(%d)", i);
			local t = getXMLString(xmlFile, key .. "#type");
			if t == nil then
				break;
			end;
			local desc = FruitUtil.fruitTypes[t];
			if desc ~= nil then
				local fillType = FruitUtil.fruitTypeToFillType[desc.index];
				local currentPS = {};
  
				local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
				self.dischargePartSystems2[fillType] = currentPS;
				if self.defaultdischargeParticleSystems == nil then
					self.defaultdischargeParticleSystems = currentPS;
				end;
			end;
			i = i + 1;
		end;
	end;
	
	--- tip right animation ---
	self.tipAnimation3 = getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim3#animationName");
	local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim3#tipRefPosition"));
	self.refAnim3X = x;
	self.refAnim3Y = y;
	self.refAnim3Z = z;
	
	self.dischargeEndTime3 = getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim3#dischargeEndTime");
	if self.dischargeEndTime3 ~= nil then
		self.dischargeEndTime3 = self.dischargeEndTime3 * 1000;
	end;
	self.dischargeStartTime3 = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.selectAbleTipAnims.selectAbleTipAnim3#dischargeStartTime"), 0)*1000;
	if self.isClient then
		self.dischargePartSystems3 = {};
		local i = 0;
		while true do
			local key = string.format("vehicle.selectAbleTipAnims.selectAbleTipAnim3.dischargeParticleSystems.dischargeParticleSystem(%d)", i);
			local t = getXMLString(xmlFile, key .. "#type");
			if t == nil then
				break;
			end;
			local desc = FruitUtil.fruitTypes[t];
			if desc ~= nil then
				local fillType = FruitUtil.fruitTypeToFillType[desc.index];
				local currentPS = {};
  
				local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
				self.dischargePartSystems3[fillType] = currentPS;
				if self.defaultdischargeParticleSystems == nil then
					self.defaultdischargeParticleSystems = currentPS;
				end;
			end;
			i = i + 1;
		end;
	end;
	
	--- lift box animation ---
	self.isBoxLifted = false;
	self.hatchAnimIdx = getXMLInt(xmlFile, "vehicle.hatchTipping#hatchAnimIdx");
	self.liftLevel = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.hatchTipping#hatchLiftLevel"), 0);
	self.liftBoxAnim = getXMLString(xmlFile, "vehicle.hatchTipping#animationName");
	
	--- call variable body function on load
	self:changeVariableBody(self.varBody.activeIdx, self.varBody.activeSubIdx, true);
end;

function GaluchoTipMode:delete()
	for _, particleSystem in pairs(self.dischargePartSystems1) do
		Utils.deleteParticleSystem(particleSystem);
	end;
	for _, particleSystem in pairs(self.dischargePartSystems2) do
		Utils.deleteParticleSystem(particleSystem);
	end;
	for _, particleSystem in pairs(self.dischargePartSystems3) do
		Utils.deleteParticleSystem(particleSystem);
	end;
end;

function GaluchoTipMode:readStream(streamId, connection)
	self:setTipMode(streamReadInt32(streamId), true);
	self:setLiftBox(streamReadBool(streamId), true);
end;
  
function GaluchoTipMode:writeStream(streamId, connection)
	streamWriteInt32(streamId, self.tipMode);
	streamWriteBool(streamId, self.isBoxLifted);
end;

function GaluchoTipMode:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		local tipMode = Utils.getNoNil(getXMLFloat(xmlFile, key.."#unloadMode"),1);
		if tipMode ~= nil then
			self:setTipMode(math.abs(tipMode), false);
		end;
	end;
	return BaseMission.VEHICLE_LOAD_OK;
end;

function GaluchoTipMode:getSaveAttributesAndNodes(nodeIdent)
	local attributes = 'unloadMode="'..tonumber(self.tipMode)..'"';
	return attributes, nil;
end;
  
function GaluchoTipMode:mouseEvent(posX, posY, isDown, isUp, button)
end;
  
function GaluchoTipMode:keyEvent(unicode, sym, modifier, isDown)
end;
  
function GaluchoTipMode:update(dt)
	if self:getIsActive() then
		if self:getIsActiveForInput() then
			if self.tipState == Trailer.TIPSTATE_CLOSED and self.capacity > 0 then
				if not self.varBody.nodes[self.varBody.activeIdx].onlyTipBack and self.numTipAnims > 1 then
					if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA4) then
						local tipMode = self.tipMode + 1;
						if tipMode > self.numTipAnims then
							tipMode = 1;
						end;
						self:setTipMode(math.abs(tipMode), false);
					end;
				end;
			end;
		end;
	end;
end;
  
function GaluchoTipMode:updateTick(dt)
	if self.isClient then
		if self.currentTipReferencePointIndex ~= nil then
			local tipAnimation = self.tipAnimations[self.currentTipReferencePointIndex];
			if (self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN) and self.fillLevel > 0 and self:getCurrentTipAnimationTime() >= tipAnimation.dischargeStartTime then
				if self.tipMode == 1 then
					Utils.setEmittingState(self.dischargePartSystems1[self.currentFillType], true);
				elseif self.tipMode == 2 then
					Utils.setEmittingState(self.dischargePartSystems2[self.currentFillType], true);
				elseif self.tipMode == 3 then
					Utils.setEmittingState(self.dischargePartSystems3[self.currentFillType], true);
				end;
			else
				Utils.setEmittingState(self.dischargePartSystems1[self.currentFillType], false);
				Utils.setEmittingState(self.dischargePartSystems2[self.currentFillType], false);
				Utils.setEmittingState(self.dischargePartSystems3[self.currentFillType], false);
			end;
			if self.hatchAnimIdx ~= nil and self.tipMode == self.hatchAnimIdx then
				if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then
					local liftPercent = (self.fillLevel/self.capacity)*100;
					if liftPercent < self.liftLevel then
						if not self.isBoxLifted then
							self:setLiftBox(not self.isBoxLifted);
						end;
					end;
				end;
				if self.tipState == Trailer.TIPSTATE_CLOSING then
					if self.isBoxLifted then
						self:setLiftBox(not self.isBoxLifted);
					end;
				end;
				if self:getAnimationTime(self.liftBoxAnim) == 0 or self:getAnimationTime(self.liftBoxAnim) == 1 then
					if self.hydraulicSoundEnabled then
						stopSample(self.hydraulicSound);
						self.hydraulicSoundEnabled = false;
					end;
				end;
			end;
		end;
		if self.varBody.nodes[self.varBody.activeIdx].onlyTipBack then
			if self.tipMode ~= self.backAnimIdx then
				self:setTipMode(math.abs(self.backAnimIdx), false);
			end;
		end;
	end;
end;

function GaluchoTipMode:draw()
	if self.isClient then
		if self.tipState == Trailer.TIPSTATE_CLOSED and self.capacity > 0 then
			if not self.varBody.nodes[self.varBody.activeIdx].onlyTipBack and self.numTipAnims > 1 then
				if self.tipMode == 1 then
					g_currentMission:addHelpButtonText(g_i18n:getText(self.tipAnimation1), InputBinding.IMPLEMENT_EXTRA4);
				elseif self.tipMode == 2 then
					g_currentMission:addHelpButtonText(g_i18n:getText(self.tipAnimation2), InputBinding.IMPLEMENT_EXTRA4);
				elseif self.tipMode == 3 then
					g_currentMission:addHelpButtonText(g_i18n:getText(self.tipAnimation3), InputBinding.IMPLEMENT_EXTRA4);
				end;
			end;
		end;	
	end;
end;

function GaluchoTipMode:setFillLevel(fillLevel, fillType, force)
	if self.isClient then
		if self.currentFillType ~= fillType or fillLevel <= 0  then
			Utils.setEmittingState(self.dischargePartSystems1[self.currentFillType], false);
			Utils.setEmittingState(self.dischargePartSystems2[self.currentFillType], false);
			Utils.setEmittingState(self.dischargePartSystems3[self.currentFillType], false);
		end;
	end;
end;

function GaluchoTipMode:setTipMode(unloadSide, noEventSend)
	SetTipModeEvent.sendEvent(self, unloadSide, noEventSend);
	-- Change unload side --
	self.tipMode = unloadSide;
	if self.tipMode == 1 then
		setTranslation(self.tippingRef, self.refAnim1X, self.refAnim1Y, self.refAnim1Z);
	end;
	if self.tipMode == 2 then
		setTranslation(self.tippingRef, self.refAnim2X, self.refAnim2Y, self.refAnim2Z);
	end;
	if self.tipMode == 3 then
		setTranslation(self.tippingRef, self.refAnim3X, self.refAnim3Y, self.refAnim3Z);
	end;
end;

function GaluchoTipMode:setLiftBox(liftBox, noEventSend)
	SetLiftBoxEvent.sendEvent(self, liftBox, noEventSend);
	-- Play lift box animation --
	self.isBoxLifted = liftBox;
	if self.isBoxLifted then
		if self.liftBoxAnim ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.liftBoxAnim, 1, nil, true);
		end;
	else
		if self.liftBoxAnim ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.liftBoxAnim, -2, nil, true);
		end;
	end;
	if not self.hydraulicSoundEnabled and self.hydraulicSound ~= nil and self:getIsActiveForSound() then
		playSample(self.hydraulicSound, 0, self.hydraulicSoundVolume, 0);
		self.hydraulicSoundEnabled = true;
	end;
end;

function GaluchoTipMode:enableTipAnimation(tipReferencePointIndex, direction, animTime)
	local animation = self.tipAnimations[tipReferencePointIndex];
	if animation ~= nil then
		local speedScale = animation.animationOpenSpeedScale;
		if direction < 0 then
			speedScale = animation.animationCloseSpeedScale;
		end
		if self.tipMode == 1 then
			if self.dischargeEndTime1 ~= nil and self.dischargeEndTime1 ~= animation.dischargeEndTime then
				animation.dischargeEndTime = self.dischargeEndTime1;
			end;
			if self.dischargeStartTime1 ~= nil and self.dischargeStartTime1 ~= animation.dischargeStartTime then
				animation.dischargeStartTime = self.dischargeStartTime1;
			end;
			if self.tipAnimation1 ~= nil and self.playAnimation ~= nil then
				self:playAnimation(self.tipAnimation1, speedScale, nil, true);
			end;
		end;
		if self.tipMode == 2 then
			if self.dischargeEndTime2 ~= nil and self.dischargeEndTime2 ~= animation.dischargeEndTime then
				animation.dischargeEndTime = self.dischargeEndTime2;
			end;
			if self.dischargeStartTime2 ~= nil and self.dischargeStartTime2 ~= animation.dischargeStartTime then
				animation.dischargeStartTime = self.dischargeStartTime2;
			end;
			if self.tipAnimation2 ~= nil and self.playAnimation ~= nil then
				self:playAnimation(self.tipAnimation2, speedScale, nil, true);
			end;
		end;
		if self.tipMode == 3 then
			if self.dischargeEndTime3 ~= nil and self.dischargeEndTime3 ~= animation.dischargeEndTime then
				animation.dischargeEndTime = self.dischargeEndTime3;
			end;
			if self.dischargeStartTime3 ~= nil and self.dischargeStartTime3 ~= animation.dischargeStartTime then
				animation.dischargeStartTime = self.dischargeStartTime3;
			end;
			if self.tipAnimation3 ~= nil and self.playAnimation ~= nil then
				self:playAnimation(self.tipAnimation3, speedScale, nil, true);
			end;
		end;
	end;
end;