--
-- IHC 1455 XL
-- Spezialization um Hilfe ein- bzw. ausblenden zu können
-- 
--
-- Author  Friedrich L.  -  Skullman
-- Date 18. Dezember 2010
-- Web www.modding-society.de
--
-- Copyright (c) Friedrich L. - All Rights Reserved.
--

  --
  -- Sprayer_new
  -- Class for all Sprayer_news
  --
  -- @author  Stefan Geiger
  -- @date  24/02/08
  --
  -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
  
  source("dataS/scripts/vehicles/specializations/SetTurnedOnEvent.lua");
  source("dataS/scripts/vehicles/specializations/SprayerAreaEvent.lua");
  source("dataS/scripts/vehicles/specializations/SprayerSetIsFillingEvent.lua");
  Sprayer_new = {};
  
  
  Sprayer_new.SPRAYTYPE_UNKNOWN = 0;
  Sprayer_new.NUM_SPRAYTYPES = 0;
  
  Sprayer_new.sprayTypes = {};
  Sprayer_new.sprayTypeIndexToDesc = {};
  
  Sprayer_new.sprayTypeToFillType = {};
  Sprayer_new.fillTypeToSprayType = {};
  
  function Sprayer_new.registerSprayType(name, pricePerLiter, litersPerSqmPerSecond, hudOverlayFilename)
      local key = "SPRAYTYPE_"..string.upper(name);
      if Sprayer_new[key] == nil then
          Sprayer_new.NUM_SPRAYTYPES = Sprayer_new.NUM_SPRAYTYPES+1;
          Sprayer_new[key] = Sprayer_new.NUM_SPRAYTYPES;
  
          local desc = {name = name, index = Sprayer_new.NUM_SPRAYTYPES};
          desc.pricePerLiter = pricePerLiter;
          desc.litersPerSqmPerSecond = litersPerSqmPerSecond;
          desc.hudOverlayFilename = hudOverlayFilename;
  
  
          Sprayer_new.sprayTypes[name] = desc;
          Sprayer_new.sprayTypeIndexToDesc[Sprayer_new.NUM_SPRAYTYPES] = desc;
  
          local fillType = Fillable.registerFillType(name)
          Sprayer_new.sprayTypeToFillType[Sprayer_new.NUM_SPRAYTYPES] = fillType;
          Sprayer_new.fillTypeToSprayType[fillType] = Sprayer_new.NUM_SPRAYTYPES;
      end;
  end;
  
  Sprayer_new.registerSprayType("fertilizer", 0.3, 0.5, "");
  Sprayer_new.registerSprayType("manure", 0.01, 0.5, "");
  Sprayer_new.registerSprayType("liquidManure", 0.01, 0.5, "");
  
function Sprayer_new.prerequisitesPresent(specializations)
      return SpecializationUtil.hasSpecialization(Fillable, specializations);
  end;
  
  function Sprayer_new:load(xmlFile)
  
      assert(self.setIsTurnedOn == nil, "Sprayer_new needs to be the first specialization which implements setIsTurnedOn");
      self.setIsTurnedOn = Sprayer_new.setIsTurnedOn;
      self.getIsTurnedOnAllowed = Sprayer_new.getIsTurnedOnAllowed;
  
      assert(self.setIsSprayer_newFilling == nil, "Sprayer_new needs to be the first specialization which implements setIsSprayer_newFilling");
      self.setIsSprayer_newFilling = Sprayer_new.setIsSprayer_newFilling;
      self.addSprayer_newFillTrigger = Sprayer_new.addSprayer_newFillTrigger;
      self.removeSprayer_newFillTrigger = Sprayer_new.removeSprayer_newFillTrigger;
  
      self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillLitersPerSecond"), 500);
      self.isSprayer_newFilling = false;
  
      self.sprayLitersPerSecond = {};
      local i=0;
      while true do
          local key = string.format("vehicle.sprayUsages.sprayUsage(%d)", i);
          if not hasXMLProperty(xmlFile, key) then
              break;
          end;
          local fillType = getXMLString(xmlFile, key.. "#fillType");
          local litersPerSecond = getXMLFloat(xmlFile, key.. "#litersPerSecond");
          if fillType ~= nil and litersPerSecond ~= nil then
              local fillTypeInt = Fillable.fillTypeNameToInt[fillType];
              if fillTypeInt ~= nil then
                  self.sprayLitersPerSecond[fillTypeInt] = litersPerSecond;
                  if self.defaultSprayLitersPerSecond == nil then
                      self.defaultSprayLitersPerSecond = litersPerSecond;
                  end;
              else
                  print("Warning: Invalid spray usage fill type '"..fillType.."' in '" .. self.configFileName.. "'");
              end;
          end;
          i = i+1;
      end;
      if self.defaultSprayLitersPerSecond == nil then
          print("Warning: No spray usage specified for '" .. self.configFileName.. "'. This Sprayer_new will not use any spray.");
          self.defaultSprayLitersPerSecond = 0;
      end;
  
      self.sprayValves = {};
  
      if self.isClient then
          local psFile = getXMLString(xmlFile, "vehicle.sprayParticleSystem#file");
          if psFile ~= nil then
           local i=0;
              while true do
                  local baseName = string.format("vehicle.sprayValves.sprayValve(%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 sprayValve = {};
                      sprayValve.particleSystems = {};
                      Utils.loadParticleSystem(xmlFile, sprayValve.particleSystems, "vehicle.sprayParticleSystem", node, false, nil, self.baseDirectory);
                      table.insert(self.sprayValves, sprayValve);
                  end;
                  i = i+1;
              end;
          end;
  
          local spraySound = getXMLString(xmlFile, "vehicle.spraySound#file");
          if spraySound ~= nil and spraySound ~= "" then
              spraySound = Utils.getFilename(spraySound, self.baseDirectory);
              self.spraySound = createSample("spraySound");
              self.spraySoundEnabled = false;
              loadSample(self.spraySound, spraySound, false);
              self.spraySoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.spraySound#pitchOffset"), 1);
              self.spraySoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.spraySound#volume"), 1);
          end;
      end;
  
      self.Sprayer_newFillTriggers = {};
      self.Sprayer_newFillActivatable = Sprayer_newFillActivatable:new(self);
  
      self.isTurnedOn = false;
      self.speedViolationMaxTime = 1000;
      self.speedViolationTimer = self.speedViolationMaxTime;
  end;
  
  function Sprayer_new:delete()
  
      g_currentMission:removeActivatableObject(self.Sprayer_newFillActivatable);
  
      for k,sprayValve in pairs(self.sprayValves) do
          Utils.deleteParticleSystem(sprayValve.particleSystems);
      end;
  
      if self.spraySound ~= nil then
          delete(self.spraySound);
      end;
  end;
  
 function Sprayer_new:readStream(streamId, connection)
      local turnedOn = streamReadBool(streamId);
      local isSprayer_newFilling = streamReadBool(streamId);
      self:setIsTurnedOn(turnedOn, true);
      self:setIsSprayer_newFilling(isSprayer_newFilling, true);
  end;
  
  function Sprayer_new:writeStream(streamId, connection)
      streamWriteBool(streamId, self.isTurnedOn);
      streamWriteBool(streamId, self.isSprayer_newFilling);
  end;
  
  function Sprayer_new:readUpdateStream(streamId, timestamp, connection)
  end;
  
  function Sprayer_new:writeUpdateStream(streamId, connection, dirtyMask)
  end;
  
  function Sprayer_new:mouseEvent(posX, posY, isDown, isUp, button)
  end;
  
  function Sprayer_new:keyEvent(unicode, sym, modifier, isDown)
  end;
  
  function Sprayer_new:update(dt)
  
      if self.isClient then
          if self:getIsActiveForInput() then
              if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
                  self:setIsTurnedOn(not self.isTurnedOn);
              end;
          end;
      end;
  
  end;
  
  function Sprayer_new:updateTick(dt)
  
      if self:getIsActive() then
          if self.isTurnedOn then
  
              self.lastSprayingArea = 0;
  
              if self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31 then
                  self.speedViolationTimer = self.speedViolationTimer - dt;
              else
                  self.speedViolationTimer = self.speedViolationMaxTime;
              end;
  
              if self.isServer then
               if self.speedViolationTimer > 0 then
                      local litersPerSecond = self.sprayLitersPerSecond[self.currentFillType];
                      if litersPerSecond == nil then
                          litersPerSecond = self.defaultSprayLitersPerSecond;
                      end
                      local usage = litersPerSecond * dt*0.001;
  
                      local hasSpray = false;
  
                      if self.capacity == 0 or self:getIsHired() then
                          hasSpray = true;
                          local sprayType = Sprayer_new.fillTypeToSprayType[self.currentFillType];
                          if sprayType ~= nil then
                              local sprayTypeDesc = Sprayer_new.sprayTypeIndexToDesc[sprayType];
                              local delta = usage*sprayTypeDesc.pricePerLiter
                              g_currentMission.missionStats.expensesTotal = g_currentMission.missionStats.expensesTotal + delta;
                              g_currentMission.missionStats.expensesSession = g_currentMission.missionStats.expensesSession + delta;
  
                              g_currentMission:addSharedMoney(-delta);
  
                              -- TODO update spray stats
                              --[[g_currentMission.missionStats.sprayUsageTotal = g_currentMission.missionStats.sprayUsageTotal + usage;
                              g_currentMission.missionStats.sprayUsageSession = g_currentMission.missionStats.sprayUsageSession + usage;]]
                          end;
                      else
                          if self.fillLevel > 0 then
                              hasSpray = true;
                              self:setFillLevel(self.fillLevel - usage, self.currentFillType);
                          end;
                      end;
  
                      if hasSpray then
                          local cuttingAreasSend = {};
                          for k,cuttingArea in pairs(self.cuttingAreas) do
                              if self:getIsAreaActive(cuttingArea) then
                                  local x,y,z = getWorldTranslation(cuttingArea.start);
                                  local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
                                  local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
  
                                  local sqm = math.abs((z1-z)*(x2-x) - (x1-x)*(z2-z)); -- this is the cross product with y=0
  
                                  --Utils.updateSprayArea(x, z, x1, z1, x2, z2);
  
                                  self.lastSprayingArea = self.lastSprayingArea + sqm;
  
                                  table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
                              end;
                          end;
                          if (table.getn(cuttingAreasSend) > 0) then
                              Sprayer_newAreaEvent.runLocally(cuttingAreasSend);
                           g_server:broadcastEvent(Sprayer_newAreaEvent:new(cuttingAreasSend));
                          end;
                      end;
                  end;
              end;
  
              if self.isClient then
                  if not self.spraySoundEnabled and self:getIsActiveForSound() then
                      playSample(self.spraySound, 0, self.spraySoundVolume, 0);
                      setSamplePitch(self.spraySound, self.spraySoundPitchOffset);
                      self.spraySoundEnabled = true;
                  end;
              end;
  
              if self.fillLevel <= 0 and self.capacity ~= 0 then
                  self:setIsTurnedOn(false, true);
              end;
          else
              self.speedViolationTimer = self.speedViolationMaxTime;
          end;
      end;
  
      if self.isSprayer_newFilling and self.isServer then
          local disableFilling = false;
          if self:allowFillType(self.Sprayer_newFillingFillType, false) then
              local oldFillLevel = self.fillLevel;
  
              local delta = self.fillLitersPerSecond*dt*0.001;
  
              local silo = g_currentMission:getSiloAmount(self.Sprayer_newFillingFillType);
              if self.Sprayer_newFillingIsSiloTrigger then
                  if silo <= 0 then
                      disableFilling = true;
                  end;
                  delta = math.min(delta, silo);
              end;
  
              self:setFillLevel(self.fillLevel + delta, self.Sprayer_newFillingFillType, true);
              local delta = self.fillLevel - oldFillLevel;
              if delta > 0 then
                  if self.Sprayer_newFillingIsSiloTrigger then
                      g_currentMission:setSiloAmount(self.Sprayer_newFillingFillType, silo - delta);
                  else
                      local sprayType = Sprayer_new.fillTypeToSprayType[self.Sprayer_newFillingFillType];
                      if sprayType ~= nil then
                          local sprayTypeDesc = Sprayer_new.sprayTypeIndexToDesc[sprayType]
  
                          local price = delta*sprayTypeDesc.pricePerLiter;
                          g_currentMission.missionStats.expensesTotal = g_currentMission.missionStats.expensesTotal + price;
                          g_currentMission.missionStats.expensesSession = g_currentMission.missionStats.expensesSession + price;
                          g_currentMission:addSharedMoney(-price);
                      end;
                  end;
              elseif self.fillLevel == self.capacity then
                  disableFilling = true;
              end;
          else
              disableFilling = true;
          end;
          if disableFilling then
              self:setIsSprayer_newFilling(false);
          end;
      end;
  end;
  
  function Sprayer_new:draw()
  
      if self.isClient then
          if self.fillLevel <= 0 and self.capacity ~= 0 then
              g_currentMission:addExtraPrintText(g_i18n:getText("FirstFillTheTool"));
          end;
  
          if self.isTurnedOn then
				
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
          else
              g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
          end;
  
          --[[if math.abs(self.speedViolationTimer - self.speedViolationMaxTime) > 2 then
              g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", tBinding.getKeyNamesOfDigitalAction(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
         end;]]
      end;
  end;
  
  function Sprayer_new:onDetach()
      if self.deactivateOnDetach then
          Sprayer_new.onDeactivate(self);
      else
          Sprayer_new.onDeactivateSounds(self);
      end;
  end;
  
  function Sprayer_new:onLeave()
      if self.deactivateOnLeave then
          Sprayer_new.onDeactivate(self);
      else
          Sprayer_new.onDeactivateSounds(self);
      end;
  end;
  function Sprayer_new:onDeactivate()
      self.speedViolationTimer = self.speedViolationMaxTime;
     -- self:setIsTurnedOn(false, true)
      Sprayer_new.onDeactivateSounds(self);
  end;
  
  function Sprayer_new:onDeactivateSounds()
      if self.spraySoundEnabled then
          stopSample(self.spraySound);
          self.spraySoundEnabled = false;
      end;
  end;
  
  function Sprayer_new:getIsTurnedOnAllowed(isTurnedOn)
      if not isTurnedOn or self.fillLevel > 0 or self.capacity == 0 then
          return true;
      end;
  end;
  
  function Sprayer_new:setIsTurnedOn(isTurnedOn, noEventSend)
      if isTurnedOn ~= self.isTurnedOn then
          if self:getIsTurnedOnAllowed(isTurnedOn) then
              SetTurnedOnEvent.sendEvent(self, isTurnedOn, noEventSend)
  
              self.isTurnedOn = isTurnedOn;
              if self.isClient then
                  for k,sprayValve in pairs(self.sprayValves) do
                      Utils.setEmittingState(sprayValve.particleSystems, self.isTurnedOn);
                  end;
  
                  if not self.isTurnedOn and self.spraySoundEnabled then
                      stopSample(self.spraySound);
                      self.spraySoundEnabled = false;
                  end;
              end;
              self.speedViolationTimer = self.speedViolationMaxTime;
          end;
      end;
  end;
  
  function Sprayer_new:setIsSprayer_newFilling(isFilling, fillType, isSiloTrigger, noEventSend)
      SprayerSetIsFillingEvent.sendEvent(self, isFilling, fillType, isSiloTrigger, noEventSend)
      if self.isSprayer_newFilling ~= isFilling then
          self.isSprayer_newFilling = isFilling;
          self.Sprayer_newFillingFillType = fillType;
          self.Sprayer_newFillingIsSiloTrigger = isSiloTrigger;
      end;
  end;
  
function Sprayer_new:addSprayer_newFillTrigger(trigger)
      if table.getn(self.Sprayer_newFillTriggers) == 0 then
          g_currentMission:addActivatableObject(self.Sprayer_newFillActivatable);
      end;
      table.insert(self.Sprayer_newFillTriggers, trigger);
  end;
  
  function Sprayer_new:removeSprayer_newFillTrigger(trigger)
      for i=1, table.getn(self.Sprayer_newFillTriggers) do
          if self.Sprayer_newFillTriggers[i] == trigger then
              table.remove(self.Sprayer_newFillTriggers, i);
              break;
          end;
      end;
      if table.getn(self.Sprayer_newFillTriggers) == 0 then
          if self.isServer then
              self:setIsSprayer_newFilling(false);
          end;
          g_currentMission:removeActivatableObject(self.Sprayer_newFillActivatable);
      end;
  end;
  
  Sprayer_newFillActivatable = {}
  local Sprayer_newFillActivatable_mt = Class(Sprayer_newFillActivatable);
  
  function Sprayer_newFillActivatable:new(Sprayer_new)
      local self = {};
      setmetatable(self, Sprayer_newFillActivatable_mt);
  
      self.Sprayer_new = Sprayer_new;
      self.activateText = "unknown";
  
      self.currentTrigger = nil;
  
      return self;
  end;
  
  
  function Sprayer_newFillActivatable:getIsActivatable()
      self.currentTrigger = nil;
      if not self.Sprayer_new:getIsActiveForInput() or self.Sprayer_new.fillLevel == self.Sprayer_new.capacity then
          return false;
      end;
      -- find the first trigger which is activable
      for i=1, table.getn(self.Sprayer_new.Sprayer_newFillTriggers) do
          local trigger = self.Sprayer_new.Sprayer_newFillTriggers[i];
          if trigger:getIsActivatable(self.Sprayer_new) then
              self.currentTrigger = trigger;
              self:updateActivateText();
              return true;
          end;
      end;
      return false;
  end;
  
  function Sprayer_newFillActivatable:onActivateObject()
      self.Sprayer_new:setIsSprayer_newFilling(not self.Sprayer_new.isSprayer_newFilling, self.currentTrigger.fillType, self.currentTrigger.isSiloTrigger);
      self:updateActivateText();
      g_currentMission:addActivatableObject(self);
  end;
  
  function Sprayer_newFillActivatable:drawActivate()
      -- TODO draw icon
  end;
  
  function Sprayer_newFillActivatable:updateActivateText()
      if self.Sprayer_new.isSprayer_newFilling then
          self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), self.Sprayer_new.typeDesc);
      else
          self.activateText = string.format(g_i18n:getText("refill_OBJECT"), self.Sprayer_new.typeDesc);
      end;
   end;