-- Fredzaza --

Regime = {};

function Regime.prerequisitesPresent(specializations)
      return true;
end;
function Regime.initSpecialization()
end
function Regime.registerOverwrittenFunctions(vehicleType)
end
function Regime.registerFunctions(vehicleType)	
end
function Regime.registerEvents(vehicleType)
end
function Regime:registerActionEventsPlayer()
end
function Regime:registerActionEventsMenu()
end

function Regime:onRegisterActionEvents(isSelected, isOnActiveVehicle)
	if isOnActiveVehicle then
		if self.Regime == nil then 
			self.Regime = {}
		else	
			self:clearActionEventsTable( self.Regime )
		end 
		for _,actionName in pairs({"patins_688_v1", "vitre_688_v1", "porte_688_v1", "regime_688_v1"}) do
			local _, eventName = self:addActionEvent(self.Regime, InputAction[actionName], self, Regime.actionCallback, true, true, false, true, nil);
	
			if isSelected then
				g_inputBinding.events[eventName].displayPriority = 1
			elseif  isOnActiveVehicle then
				g_inputBinding.events[eventName].displayPriority = 3
			end
		end
	end
end

function Regime.registerEventListeners(vehicleType)
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", Regime)
	SpecializationUtil.registerEventListener(vehicleType, "onDelete", Regime)
    SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Regime)
    SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Regime)
    --SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Regime)
    --SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Regime)
	SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Regime)
	SpecializationUtil.registerEventListener(vehicleType, "onDraw", Regime)
	SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Regime)

end

function Regime:onLoad(vehicle)	
	local spec = self.spec_regime

	self.demarrage = Regime.demarrage
	self.hautregime = Regime.hautregime
	self.regimeforce = Regime.regimeforce
	self.forceregimehaut = Regime.forceregimehaut
	self.forceregimebas = Regime.forceregimebas
	self.animpatins = Regime.animpatins
	self.animvitre = Regime.animvitre
	self.animporte = Regime.animporte
	
	self.patins = false
	self.vitre = false
	self.porte = false
	self.Regimehaut= false
	self.Regimeenhaut = false
	self.Regimeenbas = true
	self.Regimeforcage = false
	self.fonctionA = false
	self.fonctionB = false
	self.forceplayed = false
	self.forcebaisseplayed = true

	self.samples = {}
    if self.isClient then
        self.samples.ralenti = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "ralentiSound", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.hausse = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "hausseSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.haut = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "hautSound", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.baisse = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "baisseSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.hydro = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "hydroSound", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.demarage = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "demarageSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)  
		self.samples.fhausse = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "fhausseSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.fbaisse = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "fbaisseSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
		self.samples.fhaut = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.sounds", "fhautSound", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
	end
	self.godetvisualpelle = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.godetvisualpelle#index"));
	
	if self.isClient then
		self.fumepotPS = {};
		local ps = {}
		ParticleUtil.loadParticleSystem(self.xmlFile, ps, "vehicle.fumepot.particle", self.components, false, nil, self.baseDirectory);
		table.insert(self.fumepotPS, ps)
	end
end;

function Regime:onDelete() 
		g_soundManager:stopSample(self.samples.hausse)
		g_soundManager:stopSample(self.samples.haut)
		g_soundManager:stopSample(self.samples.baisse)
		g_soundManager:stopSample(self.samples.ralenti)
		g_soundManager:stopSample(self.samples.demarage)
		g_soundManager:stopSample(self.samples.fhausse)
		g_soundManager:stopSample(self.samples.fbaisse)
		g_soundManager:stopSample(self.samples.fhaut)
		if self.isClient then
			ParticleUtil.deleteParticleSystems(self.fumepotPS)
		end;	
end;

function Regime:onReadStream(streamId, connection)
    local patins = streamReadBool(streamId)
    self:animpatins(patins, true)
	local vitre = streamReadBool(streamId)
    self:animvitre(vitre, true)
	local porte = streamReadBool(streamId)
    self:animporte(porte, true)
	local Regimehaut = streamReadBool(streamId)
    self:hautregime(Regimehaut, true)
	local Regimeforcage = streamReadBool(streamId)
    self:regimeforce(Regimeforcage, true)
end;
  
function Regime:onWriteStream(streamId, connection)
    local spec = self.spec_regime
    streamWriteBool(streamId, spec.patins)
	streamWriteBool(streamId, spec.vitre)
	streamWriteBool(streamId, spec.porte)
	streamWriteBool(streamId, spec.Regimehaut)
	streamWriteBool(streamId, spec.Regimeforcage)
end;

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

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

function Regime:onUpdate(dt, vehicle)
	local spec = self.spec_regime
	local spece = self.spec_motorized
	local speci = self.spec_cylindered
	
	for i=1, table.getn(speci.movingTools) do
		local tool1 = speci.movingTools[1]
		local tool2 = speci.movingTools[2]
		local tool3 = speci.movingTools[3]
		local tool4 = speci.movingTools[4]
		local tool6 = speci.movingTools[6]
		local tool7 = speci.movingTools[7]
		local tool8 = speci.movingTools[8]
		local accInput = spece:getAxisForward()
		if tool1.lastRotSpeed > 0.0001 or tool1.lastRotSpeed < -0.0001 or tool2.lastRotSpeed > 0.0001 or tool2.lastRotSpeed < -0.0001 or tool3.lastRotSpeed > 0.0001 or tool3.lastRotSpeed < -0.0001 or tool4.lastRotSpeed > 0.0001 or tool4.lastRotSpeed < -0.0001 or tool6.lastRotSpeed > 0.0001 or tool6.lastRotSpeed < -0.0001 or tool7.lastRotSpeed > 0.0001 or tool7.lastRotSpeed < -0.0001 or tool8.lastRotSpeed > 0.0001 or tool8.lastRotSpeed < -0.0001 or spece:getCruiseControlState() == Drivable.CRUISECONTROL_STATE_ACTIVE or accInput ~= 0 then
			self.Regimeforcage = true
		else
			self.Regimeforcage = false
		end;
	end;
	if self.Regimeforcage then		
		self:regimeforce(true)
	else
		self:regimeforce(false)
	end;	
	if self.Regimehaut then
		if self.Regimeforcage then		
			if not g_soundManager:getIsSamplePlaying(self.samples.fhausse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.fbaisse, 1.5*dt) and not self.forceplayed then 
				self.forceplayed = true
				self.forcebaisseplayed = false
			end;
		else	
			if not g_soundManager:getIsSamplePlaying(self.samples.fbaisse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.fhausse, 1.5*dt) and not self.forcebaisseplayed then 
				self.forceplayed = false
				self.forcebaisseplayed = true
			end;
		end;	
	end;		
					
	if spece.isMotorStarted then	
		if not self.Regimedemarage then
			self:demarrage()
		end;
		if g_soundManager:getIsSamplePlaying(self.samples.demarage, 1.5*dt) then
			for _, ps in pairs(self.fumepotPS) do	
				ParticleUtil.setEmittingState(ps, true);
			end;
		else					
			for _, ps in pairs(self.fumepotPS) do	
				ParticleUtil.setEmittingState(ps, false);
			end;
		end;			
		if self.Regimehaut then
			if not g_soundManager:getIsSamplePlaying(self.samples.hausse, 1.5*dt) then
				if self.Regimeforcage then
					if not g_soundManager:getIsSamplePlaying(self.samples.fhausse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.fbaisse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.hausse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.baisse, 1.5*dt) and not self.fonctionA then
						g_soundManager:playSample(self.samples.fhausse)
						g_soundManager:playSample(self.samples.fhaut, 0, self.samples.fhausse)
						g_soundManager:stopSample(self.samples.haut)
						self.fonctionA = true
						self.fonctionB = false
					end;
					for _, ps in pairs(self.fumepotPS) do	
						ParticleUtil.setEmittingState(ps, true);
					end;
				else
					if not g_soundManager:getIsSamplePlaying(self.samples.fbaisse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.fhausse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.hausse, 1.5*dt) and not g_soundManager:getIsSamplePlaying(self.samples.baisse, 1.5*dt) and not self.fonctionB then
						g_soundManager:playSample(self.samples.fbaisse)
						g_soundManager:playSample(self.samples.haut, 0, self.samples.fbaisse)
						g_soundManager:stopSample(self.samples.fhaut)
						self.fonctionA = false
						self.fonctionB = true
					end;	
					for _, ps in pairs(self.fumepotPS) do	
						ParticleUtil.setEmittingState(ps, false);
					end;
				end;
			end;
		else	
			g_soundManager:stopSample(self.samples.hausse)
			g_soundManager:stopSample(self.samples.haut)
			g_soundManager:stopSample(self.samples.fhausse)
			g_soundManager:stopSample(self.samples.fbaisse)
			g_soundManager:stopSample(self.samples.fhaut)
		end;
	else
		g_soundManager:stopSample(self.samples.hausse)
		g_soundManager:stopSample(self.samples.haut)
		g_soundManager:stopSample(self.samples.baisse)
		g_soundManager:stopSample(self.samples.ralenti)
		g_soundManager:stopSample(self.samples.demarage)
		g_soundManager:stopSample(self.samples.fhausse)
		g_soundManager:stopSample(self.samples.fbaisse)
		g_soundManager:stopSample(self.samples.fhaut)

		
		self.Regimehaut = false						
		self.Regimeenhaut = false
		self.Regimeenbas = true
		self.Regimedemarage = false
		
		for _, ps in pairs(self.fumepotPS) do	
			ParticleUtil.setEmittingState(ps, false);
		end;
	end;
end;

function Regime:onUpdateTick() 
end;	
function Regime:onLeaveVehicle()
end;       
function Regime:onDraw()  
end;

function Regime:actionCallback(actionName, keyStatus, arg4, arg5, arg6)
	if keyStatus > 0 then
		if actionName == 'patins_688_v1' then
			if self.patins then
				self:animpatins(false)
			else 
				self:animpatins(true)
			end
		end
		if actionName == 'vitre_688_v1' then
			if self.vitre then
				self:animvitre(false)
			else 
				self:animvitre(true)
			end
		end
		if actionName == 'porte_688_v1' then
			if self.porte then
				self:animporte(false)
			else 
				self:animporte(true)
			end
		end
		if actionName == 'regime_688_v1' then
			if self.Regimehaut then
				self:hautregime(false)
			else 
				self:hautregime(true)
			end
		end
	end
end

function Regime:demarrage()
	local spec = self.spec_regime
	local spece = self.spec_motorized
	self.Regimedemarage = true
	if self.isClient then
		g_soundManager:playSample(self.samples.demarage)
		g_soundManager:playSample(self.samples.ralenti, 0, self.samples.demarage)
		g_soundManager:stopSamples(spece.motorSamples)
	end;
end;

function Regime:hautregime(Regimehaut, noEventSend)
	RegimehautEvent.sendEvent(self, Regimehaut, noEventSend)
	local spece = self.spec_motorized
	self.Regimehaut = Regimehaut
	if self.Regimedemarage then
		if self.Regimehaut and not self.Regimeenhaut then
			self.Regimeenhaut = true
			self.Regimeenbas = false
			g_soundManager:playSample(self.samples.hausse, 0, spece.samples.motorStart)
			g_soundManager:playSample(self.samples.haut, 0, self.samples.hausse)
			g_soundManager:stopSamples(spece.motorSamples)
			g_soundManager:stopSample(self.samples.baisse)
			g_soundManager:stopSample(self.samples.ralenti)
			g_soundManager.stopSample(self.samples.fhaut);
			g_soundManager.stopSample(self.samples.fhausse);
			g_soundManager.stopSample(self.samples.fbaisse);
		end;	
		if not self.Regimehaut and not self.Regimeenbas then
			self.Regimeenbas = true				
			self.Regimeenhaut = false
			g_soundManager:playSample(self.samples.baisse)
			g_soundManager:playSample(self.samples.ralenti, 0, self.samples.baisse)
			g_soundManager:stopSamples(spece.motorSamples)
			g_soundManager:stopSample(self.samples.hausse)
			g_soundManager:stopSample(self.samples.haut)
			g_soundManager.stopSample(self.samples.fhaut);
			g_soundManager.stopSample(self.samples.fhausse);
			g_soundManager.stopSample(self.samples.fbaisse);
		end;
	end;		
end;

function Regime:regimeforce(Regimeforcage, noEventSend)
	RegimeforcagetEvent.sendEvent(self, Regimeforcage, noEventSend)
	self.Regimeforcage = Regimeforcage		
end;

function Regime:animpatins(patins, noEventSend)
	AnimpatinsEvent.sendEvent(self, patins, noEventSend)
	self.patins = patins;
	local spece = self.spec_motorized
	if spece.isMotorStarted then	
		if self.patins then
			for name,_ in pairs(self.spec_animatedVehicle.animations) do
				self:playAnimation("patins", 1, nil, true)
			end
		else
			for name,_ in pairs(self.spec_animatedVehicle.animations) do
				self:playAnimation("patins", -1, nil, true)
			end
		end;
	end;
end;

function Regime:animvitre(vitre, noEventSend)
	AnimvitreEvent.sendEvent(self, vitre, noEventSend)
	self.vitre = vitre;
	if self.vitre then
		for name,_ in pairs(self.spec_animatedVehicle.animations) do
			self:playAnimation("vitre", 1, nil, true)
		end
	else
		for name,_ in pairs(self.spec_animatedVehicle.animations) do
			self:playAnimation("vitre", -1, nil, true)
		end
	end;
end;

function Regime:animporte(porte, noEventSend)
	AnimporteEvent.sendEvent(self, porte, noEventSend)
	self.porte = porte;
	if self.porte then
		for name,_ in pairs(self.spec_animatedVehicle.animations) do
			self:playAnimation("porte", 1, nil, true)
		end
	else
		for name,_ in pairs(self.spec_animatedVehicle.animations) do
			self:playAnimation("porte", -1, nil, true)
		end
	end;
end;

--- Event ---

AnimpatinsEvent = {};
AnimpatinsEvent_mt = Class(AnimpatinsEvent, Event);
InitEventClass(AnimpatinsEvent, "AnimpatinsEvent");

function AnimpatinsEvent:emptyNew()
    local self = Event:new(AnimpatinsEvent_mt);
    return self;
end;
function AnimpatinsEvent:new(object, patins)
	local self = AnimpatinsEvent:emptyNew()
	self.object = object;
	self.patins = patins;
	return self;
end;
function AnimpatinsEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.patins = streamReadBool(streamId);
	self:run(connection);
end;
function AnimpatinsEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.patins);
end;
function AnimpatinsEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:animpatins(self.patins, true);
	end;
end;
function AnimpatinsEvent.sendEvent(vehicle, patins, noEventSend)
	if patins ~= vehicle.patins then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(AnimpatinsEvent:new(vehicle, patins), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(AnimpatinsEvent:new(vehicle, patins));
			end;
		end;
	end;
end;

AnimvitreEvent = {};
AnimvitreEvent_mt = Class(AnimvitreEvent, Event);
InitEventClass(AnimvitreEvent, "AnimvitreEvent");

function AnimvitreEvent:emptyNew()
    local self = Event:new(AnimvitreEvent_mt);
    return self;
end;
function AnimvitreEvent:new(object, vitre)
	local self = AnimvitreEvent:emptyNew()
	self.object = object;
	self.vitre = vitre;
	return self;
end;
function AnimvitreEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.vitre = streamReadBool(streamId);
	self:run(connection);
end;
function AnimvitreEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.vitre);
end;
function AnimvitreEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:animvitre(self.vitre, true);
	end;
end;
function AnimvitreEvent.sendEvent(vehicle, vitre, noEventSend)
	if vitre ~= vehicle.vitre then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(AnimvitreEvent:new(vehicle, vitre), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(AnimvitreEvent:new(vehicle, vitre));
			end;
		end;
	end;
end;

AnimporteEvent = {};
AnimporteEvent_mt = Class(AnimporteEvent, Event);
InitEventClass(AnimporteEvent, "AnimporteEvent");

function AnimporteEvent:emptyNew()
    local self = Event:new(AnimporteEvent_mt);
    return self;
end;
function AnimporteEvent:new(object, porte)
	local self = AnimporteEvent:emptyNew()
	self.object = object;
	self.porte = porte;
	return self;
end;
function AnimporteEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.porte = streamReadBool(streamId);
	self:run(connection);
end;
function AnimporteEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.porte);
end;
function AnimporteEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:animporte(self.porte, true);
	end;
end;
function AnimporteEvent.sendEvent(vehicle, porte, noEventSend)
	if porte ~= vehicle.porte then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(AnimporteEvent:new(vehicle, porte), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(AnimporteEvent:new(vehicle, porte));
			end;
		end;
	end;
end;

RegimehautEvent = {};
RegimehautEvent_mt = Class(RegimehautEvent, Event);
InitEventClass(RegimehautEvent, "RegimehautEvent");

function RegimehautEvent:emptyNew()
    local self = Event:new(RegimehautEvent_mt);
    return self;
end;
function RegimehautEvent:new(object, Regimehaut)
	local self = RegimehautEvent:emptyNew()
	self.object = object;
	self.Regimehaut = Regimehaut;
	return self;
end;
function RegimehautEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.Regimehaut = streamReadBool(streamId);
	self:run(connection);
end;
function RegimehautEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.Regimehaut);
end;
function RegimehautEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:hautregime(self.Regimehaut, true);
	end;
end;
function RegimehautEvent.sendEvent(vehicle, Regimehaut, noEventSend)
	if Regimehaut ~= vehicle.Regimehaut then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(RegimehautEvent:new(vehicle, Regimehaut), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(RegimehautEvent:new(vehicle, Regimehaut));
			end;
		end;
	end;
end;

RegimeforcagetEvent = {};
RegimeforcagetEvent_mt = Class(RegimeforcagetEvent, Event);
InitEventClass(RegimeforcagetEvent, "RegimeforcagetEvent");

function RegimeforcagetEvent:emptyNew()
    local self = Event:new(RegimeforcagetEvent_mt);
    return self;
end;
function RegimeforcagetEvent:new(object, Regimeforcage)
	local self = RegimeforcagetEvent:emptyNew()
	self.object = object;
	self.Regimeforcage = Regimeforcage;
	return self;
end;
function RegimeforcagetEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.Regimeforcage = streamReadBool(streamId);
	self:run(connection);
end;
function RegimeforcagetEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.Regimeforcage);
end;
function RegimeforcagetEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:regimeforce(self.Regimeforcage, true);
	end;
end;
function RegimeforcagetEvent.sendEvent(vehicle, Regimeforcage, noEventSend)
	if Regimeforcage ~= vehicle.Regimeforcage then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(RegimeforcagetEvent:new(vehicle, Regimeforcage), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(RegimeforcagetEvent:new(vehicle, Regimeforcage));
			end;
		end;
	end;
end;