--
-- PickupChoke
-- Specialization for PickupChoke functionality
--
-- @author  	fruktor (www.eifok-team.de)
-- @version 	v1.0
-- @date  		01.06.2013
--
-- @history		19/11/13 -- Made compatible with John Deere 864 with VariableChamberBaler-spec - JoXXer, BJR-Modding
--

PickupChoke = {};

function PickupChoke.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(VariableChamberBaler, specializations);
end;

function PickupChoke:load(xmlFile)

	--###
	self.setIsBlocked = SpecializationUtil.callSpecializationsFunction("setIsBlocked");
	self.isBlocked = false;
	self.blockTimer = 0;
	self.blockMaxTime = 1500;	

	local name = getXMLString(xmlFile, "vehicle.pickupChoke.chokeSound#file");
    self.chokeSound = createSample("chokeSound");
    loadSample(self.chokeSound, Utils.getFilename(name, self.baseDirectory), false);		
	self.blockSoundVolume = getXMLFloat(xmlFile, "vehicle.pickupChoke.chokeSound#volume");
	self.blockSoundPitch = getXMLFloat(xmlFile, "vehicle.pickupChoke.chokeSound#pitchOffset");	
	
	--#
	self.isFirstRun = true;
	self.lastDeltaFill = 0;
	self.collectLastFillLevel = 0;
	
	self.lastFillDeltas = {};
	
	--#
	self.actLoad = 0;
	self.actLoad_Send = 0;
	self.setActLoad = SpecializationUtil.callSpecializationsFunction("setActLoad");
	
	--#
	psPath = string.format("vehicle.pickupChoke.cleaningParticle");
	local cleanPS = {};
	local particleNode = Utils.loadParticleSystem(xmlFile, cleanPS, psPath, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
	self.cleanPS = cleanPS;		
	
	psPath = string.format("vehicle.pickupChoke.cleaningParticleGrass");
	local cleanPSgrass = {};
	local particleNode = Utils.loadParticleSystem(xmlFile, cleanPSgrass, psPath, self.components, false, "$data/vehicles/particleSystems/trailerDischargeParticleSystem.i3d", self.baseDirectory);
	self.cleanPSgrass = cleanPSgrass;		

	--# 
	self.pu	= {};
	self.pu.dropFloorAnimationName = getXMLString(xmlFile, "vehicle.pickupChoke.dropFloorAnimation#name");
	self.pu.maxLoad = getXMLFloat(xmlFile, "vehicle.pickupChoke.maxLoad#value");
	self.pu.dirt = {};
	self.pu.dirt.grass = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pickupChoke.dirt#grass"));
	self.pu.dirt.wheat = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pickupChoke.dirt#wheat"));
	self.cleaningEndTime = 0;
	setVisibility( self.pu.dirt.grass, false );
	setVisibility( self.pu.dirt.wheat, false );	
	
	
	self.hud2 = {};
	self.hud2.xPos = 0.84;
	self.hud2.yPos = 0.85;
	self.hud2.hudWidth = 0.16;
	self.hud2.overlay_hud 	= Overlay:new("loadHUD_hud", 	Utils.getFilename("textures/HUD/loadHUD_hud.dds", self.baseDirectory), self.hud2.xPos, self.hud2.yPos, 			0.108, 0.039525);
	self.hud2.overlay_bg 	= Overlay:new("loadHUD_bg", 	Utils.getFilename("textures/HUD/loadHUD_bg.dds", self.baseDirectory), self.hud2.xPos, self.hud2.yPos, 			0.109, 0.039525);
	self.hud2.overlay_bar 	= Overlay:new("loadHUD_bar", 	Utils.getFilename("textures/HUD/loadHUD_barY.dds", self.baseDirectory), self.hud2.xPos+0.025, self.hud2.yPos+0.01, 0.16, 0.02190);

end;

function PickupChoke:delete()
	Utils.deleteParticleSystem(self.cleanPS);
	Utils.deleteParticleSystem(self.cleanPSgrass);	
end;

function PickupChoke:readStream(streamId, connection)
	local state = streamReadBool(streamId);
	self:setIsBlocked(state, true);
end;

function PickupChoke:writeStream(streamId, connection)
	streamWriteBool(streamId, self.isBlocked);
end;
 	
function PickupChoke:readUpdateStream(streamId, timestamp, connection)
end;

function PickupChoke:writeUpdateStream(streamId, connection, dirtyMask)
end;

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

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

function PickupChoke:update(dt)	
 	--#
 	if self.cleaningEndTime > self.time then
		if self.currentFillType == Fillable.FILLTYPE_DRYGRASS_WINDROW or self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW then
			Utils.setEmittingState(self.cleanPSgrass, true);
		else
			Utils.setEmittingState(self.cleanPS, true);
		end;
 	else
 		Utils.setEmittingState(self.cleanPSgrass, false);
		Utils.setEmittingState(self.cleanPS, false);
 	end;			
	
 	if self.isBlocked then
 		g_currentMission:addHelpButtonText( g_i18n:getText("PICKUP_CLEAN"), InputBinding.PICKUP_CLEAN );
 		if InputBinding.hasEvent(InputBinding.PICKUP_CLEAN) then
 			self:setIsBlocked(false);
 		end;
 	end;
end;

function PickupChoke:updateTick(dt)	
	--# host
 	if self.isServer and self.isPickupDown then
 		local deltaFill2 = 0;
 		if self.collectLastFillLevel ~= self.fillLevel then
 			if self.fillLevel > self.collectLastFillLevel then
 				deltaFill2 = self.fillLevel - self.collectLastFillLevel;
 			else
 				deltaFill2 = 0; 
 			end;			
 			self.collectLastFillLevel = self.fillLevel;
 		end	
 		if deltaFill2 ~= 0 and self.isFirstRun == false then
 			table.insert(self.lastFillDeltas, {t=self.time, d=deltaFill2});
 		end;
 		if self.isFirstRun == true then
 			self.isFirstRun = false;
 		end;
 		self.lastDeltaFill = deltaFill2;

 		local fill = 0;
 		if table.getn(self.lastFillDeltas) > 0 then
 			local noMoreOld = false;
 			while not noMoreOld do
 				if table.getn(self.lastFillDeltas) > 0 then
 					for i,lfd in pairs(self.lastFillDeltas) do
 						if self.time - lfd.t > 1000 then	
 							table.remove(self.lastFillDeltas, i);
 							break;
 						end
 						if i >= table.getn(self.lastFillDeltas) then
 							noMoreOld = true;
 						end;
 					end;
 				else
 					break;
 				end;
 			end
 			for i,lfd in pairs(self.lastFillDeltas) do
 				fill = fill + lfd.d;
 			end;
 		end
		
 		local maxLoad = self.pu.maxLoad;
 		self.actLoad2 = math.max(0, math.min(1, fill / maxLoad));
 		
 		self:setActLoad( self.actLoad2 ); 
 	
 		if self.actLoad2 == 1 and self.isServer then 
 			self.blockTimer = self.blockTimer + dt;
 			if self.blockTimer > self.blockMaxTime then
 				if not self.isBlocked then
 					self.blockTimer = 0;
 					self:setIsBlocked(true);
 					self.isFirstRun = true;
 				end
 			end;
 		elseif self.isServer then
 			self.blockTimer = math.max(0, self.blockTimer - dt/10);
 		end;
 		
 	end;		
end;

function PickupChoke:draw()
 	--#
 	if self.isBlocked then
 		g_currentMission:addWarning(g_i18n:getText("PICKUP_ISBLOCKED"));
 	end	
	
	--# hud should always be visible
	if self.isClient then --and self:getIsActive() then
	 	--# actual load hud
		if self.attacherVehicleCopy ~= nil then
			if (self.attacherVehicleCopy.indoorCamIndex ~= nil and self.attacherVehicleCopy.camIndex ~= self.attacherVehicleCopy.indoorCamIndex) or self.attacherVehicleCopy.indoorCamIndex == nil then
				self.hud2.overlay_bg:render();
				
				local percentage = self.actLoad_Send; 
				self.hud2.overlay_bar.width = self.hud2.hudWidth * math.min(1, percentage/2);	
				setOverlayUVs(self.hud2.overlay_bar.overlayId, 0, 0.05, 0, 1, math.min(1, percentage/2), 0.05, math.min(1, percentage/2), 1);
				self.hud2.overlay_bar:render();
					
				self.hud2.overlay_hud:render();	
				
				renderText(self.hud2.xPos+0.04, self.hud2.yPos+0.007, 0.02, string.format("%5.2f %%", 100*self.actLoad_Send));
			end;
		end;
	end;
	
end;

 --#
function PickupChoke:setIsBlocked(state, noEventSend)
	SetBlockedEvent.sendEvent(self, state, noEventSend);
	self.isBlocked = state;
	if state == true then
		if self.isClient and self:getIsActiveForSound() then
			playSample(self.chokeSound, 1, self.blockSoundVolume, 0);
		end;		
		if self.currentFillType == Fillable.FILLTYPE_DRYGRASS_WINDROW or self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW then
			setVisibility( self.pu.dirt.grass, true );
		else
			setVisibility( self.pu.dirt.wheat, true );
		end
		self:setIsTurnedOn(false, true);
	else
		if self.currentFillType == Fillable.FILLTYPE_DRYGRASS_WINDROW or self.currentFillType == Fillable.FILLTYPE_GRASS_WINDROW then
			setVisibility( self.pu.dirt.grass, false );
		else
			setVisibility( self.pu.dirt.wheat, false );
		end
		
		if self.pu.dropFloorAnimationName ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.pu.dropFloorAnimationName, 1, nil, true);
		end;
		
		self.cleaningEndTime = self.time + 1200;
	end	
end;

--#
function PickupChoke:setActLoad(load, noEventSend)
	SetActLoadEvent.sendEvent(self, load, noEventSend);
	self.actLoad_Send = load;
end;

 
--
--
--
--
SetActLoadEvent = {};
SetActLoadEvent_mt = Class(SetActLoadEvent, Event);

InitEventClass(SetActLoadEvent, "SetActLoadEvent");

function SetActLoadEvent:emptyNew()
	local self = Event:new(SetActLoadEvent_mt);
	self.className="SetActLoadEvent";
	return self;
end;

function SetActLoadEvent:new(vehicle, state)
	local self = SetActLoadEvent:emptyNew()
	self.vehicle = vehicle;
	self.state = state;
	return self;
end;

function SetActLoadEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.vehicle = networkGetObject(id);
	self.state = streamReadFloat32(streamId);
	self:run(connection);
end;

function SetActLoadEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteFloat32(streamId, self.state);
end;

function SetActLoadEvent:run(connection)
	self.vehicle:setActLoad(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetActLoadEvent:new(self.vehicle, self.state), nil, connection, self.vehicle);
	end;
end;

function SetActLoadEvent.sendEvent(vehicle, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetActLoadEvent:new(vehicle, state), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetActLoadEvent:new(vehicle, state));
		end;
	end;
end;
 

 
--
--
--
--
--
 
SetBlockedEvent = {};
SetBlockedEvent_mt = Class(SetBlockedEvent, Event);

InitEventClass(SetBlockedEvent, "SetBlockedEvent");

function SetBlockedEvent:emptyNew()
    local self = Event:new(SetBlockedEvent_mt);
    self.className="SetBlockedEvent";
    return self;
end;

function SetBlockedEvent:new(vehicle, state)
    local self = SetBlockedEvent:emptyNew()
    self.vehicle = vehicle;
	self.state = state;
	return self;
end;

function SetBlockedEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.state = streamReadBool(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function SetBlockedEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteBool(streamId, self.state);
end;

function SetBlockedEvent:run(connection)
	self.vehicle:setIsBlocked(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetBlockedEvent:new(self.vehicle, self.state), nil, connection, self.object);
	end;
end;

function SetBlockedEvent.sendEvent(vehicle, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetBlockedEvent:new(vehicle, state), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetBlockedEvent:new(vehicle, state));
		end;
	end;
end; 