--
-- seedsFiller
-- Class for seeds filler
--
-- @author  PeterJ_LS-UK modteam
-- @date  20/07/2011
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
  

seedsFiller = {};

function seedsFiller.prerequisitesPresent(specializations)
	return SpecializationUtil.hasSpecialization(Fillable, specializations);
end;
 
function seedsFiller:load(xmlFile)
  
	--Filling
	assert(self.setIsSowingMachineFilling == nil, "seedsFiller needs to be the first specialization which implements setIsSowingMachineFilling");
	self.setIsSowingMachineFilling = seedsFiller.setIsSowingMachineFilling;
	self.addSowingMachineFillTrigger = seedsFiller.addSowingMachineFillTrigger;
	self.removeSowingMachineFillTrigger = seedsFiller.removeSowingMachineFillTrigger;
  
	self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillLitersPerSecond"), 500);
	self.isSowingMachineFilling = false;
  
	self.sowingMachineFillTriggers = {};
	self.sowingMachineFillActivatable = SowingMachineFillActivatable:new(self);
 
	self.fillTypes[Fillable.FILLTYPE_SEEDS] = true;
	
	self.emptyBag = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.unloadBag#emptyBag"));
	self.overlay = Utils.getFilename("textures/seeds_hud.png", self.baseDirectory);
    self.FruitTypeOverlay = Overlay:new("hudPDAControl", self.overlay, g_currentMission.fruitSymbolX, g_currentMission.fruitSymbolY, g_currentMission.fruitSymbolSize, g_currentMission.fruitSymbolSize * (4 / 3)); 
	
	--Unloading
	assert(self.setIsUnloading == nil, "seedsFiller needs to be the first specialization which implements setIsUnloading");
	self.setIsUnloading = seedsFiller.setIsUnloading;
	self.getIsUnloadingAllowed = seedsFiller.getIsUnloadingAllowed;
  
	self.unloadLitersPerSecond = {};
	local i=0;
	while true do
		local key = string.format("vehicle.unloadBag(%d)", i);
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		local fillType = getXMLString(xmlFile, key.. "#unloadType");
		local litersPerSecond = getXMLFloat(xmlFile, key.. "#litersPerSecond");
		if fillType ~= nil and litersPerSecond ~= nil then
			local fillTypeInt = Fillable.fillTypeNameToInt[fillType];
			if fillTypeInt ~= nil then
				self.unloadLitersPerSecond[fillTypeInt] = litersPerSecond;
				if self.defaultUnloadLitersPerSecond == nil then
					self.defaultUnloadLitersPerSecond = litersPerSecond;
				end;
			else
				print("Warning: Invalid unload type '"..fillType.."' in '" .. self.configFileName.. "'");
			end;
		end;
		i = i+1;
	end;
	if self.defaultUnloadLitersPerSecond == nil then
		print("Warning: No unload type specified for '" .. self.configFileName.. "'. This bag will not use any unload type.");
		self.defaultUnloadLitersPerSecond = 0;
	end;
  
	self.unloadValves = {};
  
	if self.isClient then
		local psFile = getXMLString(xmlFile, "vehicle.unloadParticleSystem#file");
		if psFile ~= nil then
			local i=0;
			while true do
				local baseName = string.format("vehicle.unloadParticleSystem(%d)", i);
				local node = getXMLString(xmlFile, baseName.. "#index");
				if node == nil then
					break;
				end;
				node = Utils.indexToObject(self.components, node);
				if node ~= nil then
					local unloadValve = {};
					unloadValve.particleSystems = {};
					Utils.loadParticleSystem(xmlFile, unloadValve.particleSystems, "vehicle.unloadParticleSystem", node, false, nil, self.baseDirectory);
					table.insert(self.unloadValves, unloadValve);
				end;
				i = i+1;
			end;
		end;
		local unloadSound = getXMLString(xmlFile, "vehicle.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.unloadSound#pitchOffset"), 1);
			self.unloadSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.unloadSound#volume"), 1);
		end;
	end;
	
	self.minThreshold = 0.05;
	self.isUnloading = false;

	--Trigger
	self.FillableTrigger = seedsFiller.FillableTrigger;
	self.FillableTriggers = {};
  
	local FillableTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillableTrigger#index"));
	if FillableTrigger ~= nil then
		self.FillableTriggers[FillableTrigger] = {node=FillableTrigger, pipeState=2};
	end;
	for _, FillableTrigger in pairs(self.FillableTriggers) do
		addTrigger(FillableTrigger.node, "FillableTrigger", self);
	end;
  
	self.isSowerInRange = nil;
	
	--Show seeder fill level
	self.hudFillLevelBasePosX = 0.01;
	self.hudFillLevelBasePosY = 0.0149;
	self.hudFillLevelBaseWidth = 0.2;
	self.hudFillLevelBaseHeight = 0.043;
	self.FillLevelPanelPath = Utils.getFilename("textures/seederFillLevel_hud.png", self.baseDirectory);
	self.hudFillLevelBaseOverlay = Overlay:new("hudFillLevelBaseOverlay", self.FillLevelPanelPath, self.hudFillLevelBasePosX, self.hudFillLevelBasePosY, self.hudFillLevelBaseWidth, self.hudFillLevelBaseHeight);
end;
  
function seedsFiller:delete()
  
	g_currentMission:removeActivatableObject(self.sowingMachineFillActivatable);
  
	for k,unloadValve in pairs(self.unloadValves) do
		Utils.deleteParticleSystem(unloadValve.particleSystems);
	end;
  
	if self.unloadSound ~= nil then
		delete(self.unloadSound);
	end;
	for _, FillableTrigger in pairs(self.FillableTriggers) do
		removeTrigger(FillableTrigger.node);
	end;
end;
  
function seedsFiller:readStream(streamId, connection)
	local unloading = streamReadBool(streamId);
	local isSowingMachineFilling = streamReadBool(streamId);
	self:setIsUnloading(unloading, true);
	self:setIsSowingMachineFilling(isSowingMachineFilling, true);
end;
  
function seedsFiller:writeStream(streamId, connection)
	streamWriteBool(streamId, self.isUnloading);
	streamWriteBool(streamId, self.isSowingMachineFilling);
end;
  
function seedsFiller:readUpdateStream(streamId, timestamp, connection)
end;
  
function seedsFiller:writeUpdateStream(streamId, connection, dirtyMask)
end;
  
function seedsFiller:mouseEvent(posX, posY, isDown, isUp, button)
end;
  
function seedsFiller:keyEvent(unicode, sym, modifier, isDown)
end;
 
function seedsFiller:update(dt)
  
      if self.isClient then
          if self:getIsActiveForInput() then
              if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
                  self:setIsUnloading(not self.isUnloading);
              end;
          end;
      end;
end;
  
function seedsFiller:updateTick(dt)

	if self.fillLevel / self.capacity <= self.minThreshold then
		setVisibility(self.emptyBag, true);
	else
		setVisibility(self.emptyBag, false);
	end;
	if self:getIsActive() then
		if self.isUnloading then
			if self.isServer then
				local litersPerSecond = self.unloadLitersPerSecond[self.currentFillType];
				if litersPerSecond == nil then
					litersPerSecond = self.defaultUnloadLitersPerSecond;
				end;
				local usage = litersPerSecond * dt*0.001;
				if self.fillLevel > 0 then
					self:setFillLevel(self.fillLevel - usage, self.currentFillType);
				end;  
			end;
			if self.isClient then
				if not self.unloadSoundEnabled and self:getIsActiveForSound() then
					playSample(self.unloadSound, 0, self.unloadSoundVolume, 0);
					setSamplePitch(self.unloadSound, self.unloadSoundPitchOffset);
					self.unloadSoundEnabled = true;
				end;
			end;
			if self.fillLevel <= 0 and self.capacity ~= 0 then
				self:setIsUnloading(false, true);
			end;
		end;
	end;

	if self.isSowingMachineFilling and self.isServer then
		local disableFilling = false;
		if self:allowFillType(Fillable.FILLTYPE_SEEDS, false) then
			local oldFillLevel = self.fillLevel;
  
			local delta = self.fillLitersPerSecond*dt*0.001;
  
			local silo = g_currentMission:getSiloAmount(Fillable.FILLTYPE_SEEDS);
  
			self:setFillLevel(self.fillLevel + delta, Fillable.FILLTYPE_SEEDS, true);
			local delta = self.fillLevel - oldFillLevel;
			if delta > 0 then
				local price = delta*g_seedsPricePerLiter;
				g_currentMission.missionStats.expensesTotal = g_currentMission.missionStats.expensesTotal + price;
				g_currentMission.missionStats.expensesSession = g_currentMission.missionStats.expensesSession + price;
  
				g_currentMission:addSharedMoney(-price);
			elseif self.fillLevel == self.capacity then
				disableFilling = true;
			end;
		else
			disableFilling = true;
		end;
		if disableFilling then
			self:setIsSowingMachineFilling(false);
		end;
	end;

	if self.isServer and self:getIsActive() then
		if self.isUnloading and self.isSowerInRange ~= nil then
			local fillable = self.isSowerInRange;
			if fillable.setFillLevel ~= nil then
				for fillType,v in pairs(fillable.fillTypes) do
					if fillType == self.currentFillType and fillable.rootNode ~= self.rootNode then
						if  fillable.fillLevel ~= fillable.capacity  then
							local litersPerSecond = self.unloadLitersPerSecond[self.currentFillType];
							if litersPerSecond == nil then
								litersPerSecond = self.defaultUnloadLitersPerSecond;
							end;
							local usage = litersPerSecond * dt*0.001;
							fillable:resetFillLevelIfNeeded(Fillable.FILLTYPE_SEEDS);
							fillable:setFillLevel(fillable.fillLevel + usage, Fillable.FILLTYPE_SEEDS);
						end;
					end;
				end;
			end;
		end;
	end;
end;
  
function seedsFiller:draw()

	if self.isClient then
		if self.fillLevel <= 0 and self.capacity ~= 0 then
				g_currentMission:addExtraPrintText(g_i18n:getText("FirstFillTheTool"));
		end;
		if self.fillLevel > 0 then
			self.FruitTypeOverlay:render();
			if self.isUnloading then
				g_currentMission:addHelpButtonText(g_i18n:getText("StopSeeds"), InputBinding.IMPLEMENT_EXTRA);
			else
				g_currentMission:addHelpButtonText(g_i18n:getText("StartSeeds"), InputBinding.IMPLEMENT_EXTRA);
			end;
		end;
	end;
	if self:getIsActive() then
		if self.isSowerInRange ~= nil then
			local fillable = self.isSowerInRange;
			if self.isSowerInRange.fillLevel ~= nil then
				for fillType,v in pairs(fillable.fillTypes) do
					if fillType == self.currentFillType then
						local percent = (self.isSowerInRange.fillLevel / self.isSowerInRange.capacity) * 100;
						setTextBold(true);
						setTextAlignment(RenderText.ALIGN_CENTER);
						--setTextColor(0, 0, 0, 1);
						renderText(self.hudFillLevelBasePosX + self.hudFillLevelBaseWidth / 2 + 0.003, self.hudFillLevelBasePosY + 0.0115, 0.024, string.format("%d (%d%%)", self.isSowerInRange.fillLevel, percent));
						self.hudFillLevelBaseOverlay:render();
					end;
				end;
			end;
		end;
	end;
end;

function seedsFiller:onAttach(attacherVehicle)
	setCenterOfMass(self.components[1].node, 0, 2.05, 0);
end;
 
function seedsFiller:onDetach()
	if self.deactivateOnDetach then
		seedsFiller.onDeactivate(self);
	else
		seedsFiller.onDeactivateSounds(self);
	end;
	setCenterOfMass(self.components[1].node, 0, -0.3, 0);
end;
  
function seedsFiller:onLeave()
	if self.deactivateOnLeave then
		seedsFiller.onDeactivate(self);
	else
		seedsFiller.onDeactivateSounds(self);
	end;
end;
  
function seedsFiller:onDeactivate()
	self:setIsUnloading(false, true)
	seedsFiller.onDeactivateSounds(self);
end;
  
function seedsFiller:onDeactivateSounds()
	if self.unloadSoundEnabled then
		stopSample(self.unloadSound);
		self.unloadSoundEnabled = false;
	end;
end;
  
function seedsFiller:getIsUnloadingAllowed(isUnloading)
	if not isUnloading or self.fillLevel > 0 or self.capacity == 0 then
		return true;
	end;
end;
  
function seedsFiller:setIsUnloading(isUnloading, noEventSend)
	if isUnloading ~= self.isUnloading then
		if self:getIsUnloadingAllowed(isUnloading) then
			SetUnloadingEvent.sendEvent(self, isUnloading, noEventSend)
  
			self.isUnloading = isUnloading;
			if self.isClient then
				for k,unloadValve in pairs(self.unloadValves) do
					Utils.setEmittingState(unloadValve.particleSystems, self.isUnloading);
				end;
  
				if not self.isUnloading and self.unloadSoundEnabled then
					stopSample(self.unloadSound);
					self.unloadSoundEnabled = false;
				end;
			end;
		end;
	end;
end;
  
function seedsFiller:setIsSowingMachineFilling(isFilling, noEventSend)
    SeedsSetIsFillingEvent.sendEvent(self, isFilling, noEventSend)
	if self.isSowingMachineFilling ~= isFilling then
		self.isSowingMachineFilling = isFilling;
	end;
end;
  
function seedsFiller:addSowingMachineFillTrigger(trigger)
	if table.getn(self.sowingMachineFillTriggers) == 0 then
		g_currentMission:addActivatableObject(self.sowingMachineFillActivatable);
	end;
	table.insert(self.sowingMachineFillTriggers, trigger);
end;
  
function seedsFiller:removeSowingMachineFillTrigger(trigger)
	for i=1, table.getn(self.sowingMachineFillTriggers) do
		if self.sowingMachineFillTriggers[i] == trigger then
			table.remove(self.sowingMachineFillTriggers, i);
			break;
		end;
	end;
	if table.getn(self.sowingMachineFillTriggers) == 0 then
		if self.isServer then
			self:setIsSowingMachineFilling(false);
		end;
		g_currentMission:removeActivatableObject(self.sowingMachineFillActivatable);
	end;
end;

function seedsFiller:FillableTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	if onEnter or onLeave then
		local seeder = g_currentMission.nodeToVehicle[otherShapeId];
		if seeder ~= nil then
			if seeder ~= self and seeder.setFillLevel	then
				if onEnter then
					self.isSowerInRange = (seeder);
				else
					self.isSowerInRange = nil;
				end;
			end;
		end;
	end;
end;
 
 
SowingMachineFillActivatable = {}
local SowingMachineFillActivatable_mt = Class(SowingMachineFillActivatable);
  
function SowingMachineFillActivatable:new(sowingMachine)
	local self = {};
	setmetatable(self, SowingMachineFillActivatable_mt);
  
	self.sowingMachine = sowingMachine;
	self.activateText = "unknown";
  
	self.currentTrigger = nil;
  
	return self;
end;

function SowingMachineFillActivatable:getIsActivatable()
	self.currentTrigger = nil;
	if not self.sowingMachine:getIsActiveForInput() or self.sowingMachine.fillLevel == self.sowingMachine.capacity then
		return false;
	end;
	if table.getn(self.sowingMachine.sowingMachineFillTriggers) > 0 then
		self.currentTrigger = self.sowingMachine.sowingMachineFillTriggers[1];
		self:updateActivateText();
		return true;
	end;
	return false;
end;
  
function SowingMachineFillActivatable:onActivateObject()
	self.sowingMachine:setIsSowingMachineFilling(not self.sowingMachine.isSowingMachineFilling, self.currentTrigger.fillType, self.currentTrigger.isSiloTrigger);
	self:updateActivateText();
	g_currentMission:addActivatableObject(self);
end;
  
function SowingMachineFillActivatable:drawActivate()
end;
  
function SowingMachineFillActivatable:updateActivateText()
	if self.sowingMachine.isSowingMachineFilling then
		self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), self.sowingMachine.typeDesc);
	else
		self.activateText = string.format(g_i18n:getText("refill_OBJECT"), self.sowingMachine.typeDesc);
	end;
end;