--
-- bulkKit
-- Class for all bulk tolls
--
-- @author  PeterJ - euroDZN
-- @date  17/06/2013
--
-- http://eurodzn.wordpress.com/
--
-- Copyright (C) euroDZN, Confidential, All Rights Reserved.
  
bulkKit = {};

function bulkKit.prerequisitesPresent(specializations)
	return SpecializationUtil.hasSpecialization(Fillable, specializations);
end;
  
function bulkKit:load(xmlFile)

	self.setIsTurnedOn = bulkKit.setIsTurnedOn;
	self.getIsTurnedOnAllowed = bulkKit.getIsTurnedOnAllowed;

	self.setIsBulkKitFilling = bulkKit.setIsBulkKitFilling;
	self.addSprayerFillTrigger = bulkKit.addSprayerFillTrigger;
	self.removeSprayerFillTrigger = bulkKit.removeSprayerFillTrigger;
	self.addSowingMachineFillTrigger = bulkKit.addSowingMachineFillTrigger;
	self.removeSowingMachineFillTrigger = bulkKit.removeSowingMachineFillTrigger;

	self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.bulkKit#fillLitersPerSecond"), 100);
	self.isBulkKitFilling = false;

	self.unloadLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.bulkKit#unloadLitersPerSecond"), 100);
	self.isUnloading = false;

	-- Unload particle/node/sound
	self.unloadParticleSystems = {};
	local psName = "vehicle.bulkKit.unloadParticleSystem";
	Utils.loadParticleSystem(xmlFile, self.unloadParticleSystems, psName, self.components, false, nil, self.baseDirectory)
	self.unloadParticleSystemActive = false;
	
	if self.isClient then
		local unloadSound = getXMLString(xmlFile, "vehicle.bulkKit.unloadSound#file");
		if unloadSound ~= nil and unloadSound ~= "" then
			unloadSound = Utils.getFilename(unloadSound, self.baseDirectory);
			self.unloadSound = createSample("unloadSound");
			self.unloadSoundEnabled = false;
			loadSample(self.unloadSound, unloadSound, false);
			self.unloadSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.bulkKit.unloadSound#pitchOffset"), 1);
			self.unloadSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.bulkKit.unloadSound#volume"), 1);
			setSamplePitch(self.unloadSound, self.unloadSoundPitchOffset);
		end;
	end;
  
	self.bulkKitTriggers = {};
	self.bulkKitActivatable = BulkKitFillActivatable:new(self);
	
	-- Tool in range trigger
	self.FillableTrigger = bulkKit.FillableTrigger;
	self.FillableTriggers = {};
  
	local FillableTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.bulkKit#fillableTrigger"));
	if FillableTrigger ~= nil then
		self.FillableTriggers[FillableTrigger] = {node=FillableTrigger};
	end;
	for _, FillableTrigger in pairs(self.FillableTriggers) do
		addTrigger(FillableTrigger.node, "FillableTrigger", self);
	end;
	self.isFillableToolInRange = nil;
	
	-- Center of mass
	local dx, dy, dz = getCenterOfMass(self.components[1].node);
	self.defaultCenterOfMass = {dx,dy,dz};
	local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.bulkKit#centerOfMassAttached"));
	self.centerOfMassAttached = {x,y,z};
	
	-- Show fill level of machine in range
	self.hudFillLevelBasePosX = 0.051;
	self.hudFillLevelBasePosY = 0.0149;
	self.hudFillLevelBaseWidth = 0.2;
	self.hudFillLevelBaseHeight = 0.043;
	self.hudFillLevelBarWidth = 0.168;
	self.hudFillLevelOverlay = Overlay:new("hudFillLevelOverlay", "dataS2/menu/hud/vehicleHUD_barGold.png", self.hudFillLevelBasePosX + 0.0228, self.hudFillLevelBasePosY + 0.003, self.hudFillLevelBaseWidth - 0.03, self.hudFillLevelBaseHeight - 0.012);
	self.FillLevelBasePath = Utils.getFilename("textures/FillLevelBase.png", self.baseDirectory);
	self.hudFillLevelBase = Overlay:new("hudFillLevelBase", self.FillLevelBasePath, self.hudFillLevelBasePosX, self.hudFillLevelBasePosY, self.hudFillLevelBaseWidth, self.hudFillLevelBaseHeight);
	self.FillLevelFramePath = Utils.getFilename("textures/FillLevelFrame.png", self.baseDirectory);
	self.hudFillLevelFrame = Overlay:new("hudFillLevelFrame", self.FillLevelFramePath, self.hudFillLevelBasePosX, self.hudFillLevelBasePosY, self.hudFillLevelBaseWidth, self.hudFillLevelBaseHeight);

	-- Render fill type
	local fillTypeOverlayFile = getXMLString(xmlFile, "vehicle.bulkKit.fillTypeOverlay#file");
	if fillTypeOverlayFile ~= nil then
		fillTypeOverlayFile = Utils.getFilename(fillTypeOverlayFile, self.baseDirectory);
		self.fillTypeOverlay = Overlay:new("bulkFillType", fillTypeOverlayFile, g_currentMission.fruitSymbolX, g_currentMission.fruitSymbolY, g_currentMission.fruitSymbolSize, g_currentMission.fruitSymbolSize * (4 / 3)); 
	end;
	local fillTypeOverlayFile2 = getXMLString(xmlFile, "vehicle.bulkKit.fillTypeOverlay#file2");
	if fillTypeOverlayFile2 ~= nil then
		fillTypeOverlayFile2 = Utils.getFilename(fillTypeOverlayFile2, self.baseDirectory);
		self.fillTypeOverlay2 = Overlay:new("bulkFillType2", fillTypeOverlayFile2, g_currentMission.fruitSymbolX, g_currentMission.fruitSymbolY, g_currentMission.fruitSymbolSize, g_currentMission.fruitSymbolSize * (4 / 3)); 
	end;
end;

function bulkKit:delete()
	g_currentMission:removeActivatableObject(self.bulkKitActivatable);
	Utils.deleteParticleSystem(self.unloadParticleSystems);
	if self.unloadSound ~= nil then
		delete(self.unloadSound);
		self.unloadSoundEnabled = false;
	end;
	for _, FillableTrigger in pairs(self.FillableTriggers) do
		removeTrigger(FillableTrigger.node);
	end;
end;

function bulkKit:readStream(streamId, connection)
	local turnedOn = streamReadBool(streamId);
	local isBulkKitFilling = streamReadBool(streamId);
	self:setIsTurnedOn(turnedOn, true);
	self:setIsBulkKitFilling(isBulkKitFilling, true);
end;

function bulkKit:writeStream(streamId, connection)
	streamWriteBool(streamId, self.isUnloading);
	streamWriteBool(streamId, self.isBulkKitFilling);
end;

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

function bulkKit:keyEvent(unicode, sym, modifier, isDown)
end;
  
function bulkKit:update(dt)

	if self.isClient then
		if self.fillLevel > 0 and self:getIsActiveForInput() then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
				self:setIsTurnedOn(not self.isUnloading);
			end;
		end;
	end;
  
end;

function bulkKit:updateTick(dt)

	if self:getIsActive() then
		if self.isUnloading then
			if not self:getIsTurnedOnAllowed(true) then
				self:setIsTurnedOn(false);
			end;
			if self.isServer then
				local usage = self.unloadLitersPerSecond*dt*0.001;
				if self.fillLevel > 0 then
					self:setFillLevel(self.fillLevel - usage, self.currentFillType);
				end;  
			end;
			if self.isFillableToolInRange ~= nil then
				local fillableTool = self.isFillableToolInRange;
				if fillableTool.setFillLevel ~= nil and fillableTool.rootNode ~= self.rootNode then
					for fillType,v in pairs(fillableTool.fillTypes) do
						if fillType == self.currentFillType then
							if fillableTool.fillLevel ~= fillableTool.capacity then
								local usage = self.unloadLitersPerSecond*dt*0.001;
								fillableTool:setFillLevel(fillableTool.fillLevel + usage, self.currentFillType);
							else
								self:setIsTurnedOn(false);
							end; 	
						end;
					end;
				end;
			end;
			if self.isClient then
				if not self.unloadSoundEnabled and self.unloadSound ~= nil and self:getIsActiveForSound() then
					playSample(self.unloadSound, 0, self.unloadSoundVolume, 0);
					self.unloadSoundEnabled = true;
				end;
			end;
			if self.fillLevel <= 0 and self.capacity ~= 0 then
				self:setIsTurnedOn(false);
			end;
		end;
		if self.isClient then
			if not self.isUnloading and self.unloadSoundEnabled then
				stopSample(self.unloadSound);
				self.unloadSoundEnabled = false;
			end;
		end;
	end;
	if self.isServer and self.isBulkKitFilling then
		local delta = 0;
		if self.bulkKitTrigger ~= nil then
			delta = self.fillLitersPerSecond*dt*0.001;
			if self.bulkKitTrigger.fillSprayer ~= nil then
				delta = self.bulkKitTrigger:fillSprayer(self, delta);
			end;
			if self.bulkKitTrigger.fillSowingMachine ~= nil then
				delta = self.bulkKitTrigger:fillSowingMachine(self, delta);
			end;
		end;
		if delta <= 0 then
			self:setIsBulkKitFilling(false);
		end;
	end;
end;

function bulkKit:draw()

	if self.isClient then
		if self.currentFillType == Fillable.FILLTYPE_SEEDS then
			if self.fillTypeOverlay ~= nil then
				self.fillTypeOverlay:render();
			end;
		elseif self.currentFillType == Fillable.FILLTYPE_FERTILIZER then
			if self.fillTypeOverlay2 ~= nil then
				self.fillTypeOverlay2:render();
			end;
		end;
		if self:getIsActiveForInput(true) then
			if not self:getIsTurnedOnAllowed(true) and self.fillLevel <= 0 then
				g_currentMission:addExtraPrintText(g_i18n:getText("FirstFillTheTool"));
			end;
			if self.fillLevel > 0 then
				if self.isUnloading then
					g_currentMission:addHelpButtonText(g_i18n:getText("StopUnload"), InputBinding.IMPLEMENT_EXTRA);
				else
					g_currentMission:addHelpButtonText(g_i18n:getText("StartUnload"), InputBinding.IMPLEMENT_EXTRA);
				end;
			end;
		end;
	end;
	if self:getIsActive() and not g_currentMission.missionPDA.showPDA then
		if self.isFillableToolInRange ~= nil then
			local fillable = self.isFillableToolInRange;
			if fillable.setFillLevel ~= nil and fillable.rootNode ~= self.rootNode then
				for fillType,v in pairs(fillable.fillTypes) do
					if fillType == self.currentFillType then
						if fillable.fillLevel ~= nil and fillable.capacity > 0 then
							self.hudFillLevelBase:render();
							local percent = (fillable.fillLevel / fillable.capacity) * 100;
							setTextBold(true);
							setTextAlignment(RenderText.ALIGN_CENTER);
							setTextColor(0, 0, 0, 1);
							renderText(self.hudFillLevelBasePosX + self.hudFillLevelBaseWidth / 2 + 0.003, self.hudFillLevelBasePosY + 0.0083, 0.024, string.format("%d (%d%%)", fillable.fillLevel, percent));
							setTextColor(1, 1, 1, 1);
							renderText(self.hudFillLevelBasePosX + self.hudFillLevelBaseWidth / 2 + 0.003, self.hudFillLevelBasePosY + 0.0113, 0.024, string.format("%d (%d%%)", fillable.fillLevel, percent));
							setTextBold(false);
							self.hudFillLevelOverlay.width = self.hudFillLevelBarWidth * (fillable.fillLevel / fillable.capacity);
							setOverlayUVs(self.hudFillLevelOverlay.overlayId, 0, 0.05, 0, 1, fillable.fillLevel / fillable.capacity, 0.05, fillable.fillLevel / fillable.capacity, 1);
							self.hudFillLevelOverlay:render();
							self.hudFillLevelFrame:render();
						end;
					end;
				end;
			end;
		end;
	end;
end;

function bulkKit:onAttach(attacherVehicle)
	if self.defaultCenterOfMass ~= nil and self.centerOfMassAttached ~= nil then
		setCenterOfMass(self.components[1].node, unpack(self.centerOfMassAttached));
	end;
end;

function bulkKit:onDetach()
	if self.deactivateOnDetach then
		bulkKit.onDeactivate(self);
	else
		bulkKit.onDeactivateSounds(self);
	end;
	if self.defaultCenterOfMass ~= nil and self.centerOfMassAttached ~= nil then
		setCenterOfMass(self.components[1].node, unpack(self.defaultCenterOfMass));
	end;
end;

function bulkKit:onLeave()
	if self.deactivateOnLeave then
		bulkKit.onDeactivate(self);
	else
		bulkKit.onDeactivateSounds(self);
	end;
end;
  
function bulkKit:onDeactivate()
	self.speedViolationTimer = self.speedViolationMaxTime;
	self:setIsTurnedOn(false, true)
	bulkKit.onDeactivateSounds(self);
end;
  
function bulkKit:onDeactivateSounds()
	if self.unloadSoundEnabled then
		stopSample(self.unloadSound);
		self.unloadSoundEnabled = false;
	end;
end;
  
function bulkKit:getIsTurnedOnAllowed(isUnloading)
	if not isUnloading or self.fillLevel > 0 or self.capacity == 0 then
		return true;
	end;
	local fillType = self.currentFillType;
	if fillType == Fillable.FILLTYPE_UNKNOWN then
		fillType = self:getFirstEnabledFillType();
	end;
	return false;
end;

function bulkKit:setIsTurnedOn(isUnloading, noEventSend)
	if isUnloading ~= self.isUnloading then
		if self:getIsTurnedOnAllowed(isUnloading) then
			SetTurnedOnEvent.sendEvent(self, isUnloading, noEventSend)
  
			self.isUnloading = isUnloading;
			if self.isClient then
				Utils.setEmittingState(self.unloadParticleSystems, self.isUnloading);
			end;
		end;
	end;
end;
  
function bulkKit:setIsBulkKitFilling(isFilling, noEventSend)
	setBulkKitFillingEvent.sendEvent(self, isFilling, noEventSend)
	if self.isBulkKitFilling ~= isFilling then
		self.isBulkKitFilling = isFilling;
		if isFilling then
			self.bulkKitTrigger = nil;
			for i=1, table.getn(self.bulkKitTriggers) do
				local trigger = self.bulkKitTriggers[i];
				if trigger:getIsActivatable(self) then
					self.bulkKitTrigger = trigger;
					break;
				end;
			end;
		end;
	end;
end;
--- sprayer trigger ---
function bulkKit:addSprayerFillTrigger(trigger)
	if table.getn(self.bulkKitTriggers) == 0 then
		g_currentMission:addActivatableObject(self.bulkKitActivatable);
	end;
	table.insert(self.bulkKitTriggers, trigger);
end;
  
function bulkKit:removeSprayerFillTrigger(trigger)
	for i=1, table.getn(self.bulkKitTriggers) do
		if self.bulkKitTriggers[i] == trigger then
			table.remove(self.bulkKitTriggers, i);
			break;
		end;
	end;
	if table.getn(self.bulkKitTriggers) == 0 or trigger == self.bulkKitTrigger then
		if self.isServer then
			self:setIsBulkKitFilling(false);
		end;
		if table.getn(self.bulkKitTriggers) == 0 then
			g_currentMission:removeActivatableObject(self.bulkKitActivatable);
		end;
	end;
end;
--- sower trigger ---
function bulkKit:addSowingMachineFillTrigger(trigger)
	if table.getn(self.bulkKitTriggers) == 0 then
		g_currentMission:addActivatableObject(self.bulkKitActivatable);
	end;
	table.insert(self.bulkKitTriggers, trigger);
end;
  
function bulkKit:removeSowingMachineFillTrigger(trigger)
	for i=1, table.getn(self.bulkKitTriggers) do
		if self.bulkKitTriggers[i] == trigger then
			table.remove(self.bulkKitTriggers, i);
			break;
		end;
	end;
	if table.getn(self.bulkKitTriggers) == 0 then
		if self.isServer then
			self:setIsBulkKitFilling(false);
		end;
		g_currentMission:removeActivatableObject(self.bulkKitActivatable);
	end;
end;

function bulkKit:FillableTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	if onEnter or onLeave then
		local fillAbleObject = g_currentMission.nodeToVehicle[otherShapeId];
		if fillAbleObject ~= nil then
			if fillAbleObject ~= self and fillAbleObject.setFillLevel ~= nil then
				if onEnter then
					self.isFillableToolInRange = (fillAbleObject);
				else
					self.isFillableToolInRange = nil;
				end;
			end;
		end;
	end;
end;
  
BulkKitFillActivatable = {}
local BulkKitFillActivatable_mt = Class(BulkKitFillActivatable);

function BulkKitFillActivatable:new(bulkKit)
	local self = {};
	setmetatable(self, BulkKitFillActivatable_mt);
  
	self.bulkKit = bulkKit;
	self.activateText = "unknown";
  
	return self;
end;
 
function BulkKitFillActivatable:getIsActivatable()
	if self.bulkKit:getIsActiveForInput() and self.bulkKit.fillLevel < self.bulkKit.capacity then
		for i=1, table.getn(self.bulkKit.bulkKitTriggers) do
			local trigger = self.bulkKit.bulkKitTriggers[i];
			if trigger:getIsActivatable(self.bulkKit) then
				self:updateActivateText();
				return true;
			end;
		end;
	end;
	return false;
end;

function BulkKitFillActivatable:onActivateObject()
	self.bulkKit:setIsBulkKitFilling(not self.bulkKit.isBulkKitFilling);
	self:updateActivateText();
	g_currentMission:addActivatableObject(self);
end;

function BulkKitFillActivatable:drawActivate()
end;
  
function BulkKitFillActivatable:updateActivateText()
	if self.bulkKit.isBulkKitFilling then
		self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), self.bulkKit.typeDesc);
	else
		self.activateText = string.format(g_i18n:getText("refill_OBJECT"), self.bulkKit.typeDesc);
	end;
end;

 
setBulkKitFillingEvent = {};
setBulkKitFillingEvent_mt = Class(setBulkKitFillingEvent, Event);

InitEventClass(setBulkKitFillingEvent, "setBulkKitFillingEvent");

function setBulkKitFillingEvent:emptyNew()
	local self = Event:new(setBulkKitFillingEvent_mt);
	return self;
end;

function setBulkKitFillingEvent:new(object, isFilling)
	local self = setBulkKitFillingEvent:emptyNew()
	self.object = object;
	self.isBulkKitFilling = isFilling;
	return self;
end;

function setBulkKitFillingEvent:readStream(streamId, connection)
	self.object = networkGetObject(streamReadInt32(streamId));
	self.isBulkKitFilling = streamReadBool(streamId);
	self:run(connection);
end;

function setBulkKitFillingEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.isBulkKitFilling);
end;

function setBulkKitFillingEvent:run(connection)
	if not connection:getIsServer() then
	g_server:broadcastEvent(self, false, connection, self.object);
	end;
	self.object:setIsBulkKitFilling(self.isBulkKitFilling, true);
end;

function setBulkKitFillingEvent.sendEvent(object, isFilling, noEventSend)
	if isFilling ~= object.isSprayerFilling then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(setBulkKitFillingEvent:new(object, isFilling), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(setBulkKitFillingEvent:new(object, isFilling));
			end;
		end;
	end;
end;