---
-- ChargeSowing
-- This is the specialization for ChargeSowings
--
-- @author  Claus G. Pedersen (Satis)
-- @date  29/12/12
--
-- Copyright Satis (C) 2012
-- Copyright Note: You are allowed to redistribute, use and edit it as long I'm credited for the original script.
-- Edited by @poc@lypse (Ls-Modteam-France)

local translationList = {
  ["fr"] = {   
    ["ChargeSowing_chargeOn"] = "Ouvrir les trappes",
    ["ChargeSowing_chargeOff"] = "Fermer les trappes",
    ["ChargeSowing_isEmpty"] = "%s est vide!",   
  },
  ["en"] = {   
    ["ChargeSowing_chargeOn"] = "Charge On",
    ["ChargeSowing_chargeOff"] = "Charge Off",
    ["ChargeSowing_isEmpty"] = "%s is empty!",   
  },
  ["de"] = {   
    ["ChargeSowing_chargeOn"] = "überladen an",
    ["ChargeSowing_chargeOff"] = "überladen aus",
    ["ChargeSowing_isEmpty"] = "%s ist leer!",   
  },
};
local lang = g_languageShort;
if translationList[lang] == nil then lang = "en"; end;
for i18nString, text in pairs(translationList[lang]) do
  if not g_i18n:hasText(i18nString) then
    g_i18n:setText(i18nString, text);
  end;
end;



ChargeSowing = {};

function ChargeSowing.prerequisitesPresent(specializations)
  return SpecializationUtil.hasSpecialization(Trailer, specializations);
end;

function ChargeSowing:load(xmlFile)
	
  local aNameSearch = { "vehicle.name." .. g_languageShort, "vehicle.name.en", "vehicle.name", "vehicle#type" };
  local xmlKey = "vehicle.ChargeSowing.";
  local i = 0;
  local tempFile = "";
  local removeItem = false;

  
  self.onChargeTrigger = ChargeSowing.onChargeTrigger; 
  self.handleChargeTip = SpecializationUtil.callSpecializationsFunction("handleChargeTip");
  self.handlePipeParticles = SpecializationUtil.callSpecializationsFunction("handlePipeParticles");
  self.handleChargeTriggers = SpecializationUtil.callSpecializationsFunction("handleChargeTriggers"); 
  self.handleGrainTransfer = SpecializationUtil.callSpecializationsFunction("handleGrainTransfer");
 
 
  self.isCharging = false;
  self.sendIsCharging = false;
  self.isChargTipping = false;
  self.lastAttacherVehicle = nil;

 
  self.chargeTriggerList = {};
  self.isTrailerInRange = false;
  self.sendIsTrailerInRange = false;
  self.trailerFound = false;
  self.trailerToOverload = nil;
  self.ULWName = "";

  if self.isClient then
 
    for nIndex, sXMLPath in pairs(aNameSearch) do
      self.ULWName = getXMLString(xmlFile, sXMLPath);
      if self.ULWName ~= nil then break; end;
    end;
    if self.ULWName == nil then self.ULWName = g_i18n:getText("UNKNOWN") end;

 
    self.canChargeTip = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.ChargeSowing#canChargeTip"), false);

 

    self.chargeOverlay = getXMLString(xmlFile, xmlKey .. "chargeOverlay#file");
    if self.chargeOverlay ~= nil then
      tempFile = Utils.getFilename(self.chargeOverlay, self.baseDirectory);
      self.chargeOverlay = Overlay:new("hudPDAControl", tempFile, g_currentMission.hudTipperOverlay.x, g_currentMission.hudTipperOverlay.y, g_currentMission.hudTipperOverlay.width, g_currentMission.hudTipperOverlay.height);
    end;

 
 
    self.pipeParticles = {};
    local i = 0;
    while true do
  	  local key = string.format(xmlKey .. "pipeParticles.pipeParticle(%d)", i);
      local t = getXMLString(xmlFile, key .. "#type");
      if t == nil then
       	break;
      end;
      
      local fillType = Fillable.fillTypeNameToInt[t];
      if fillType ~= nil then
  	    local currentPS = {};
           local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "particleSystems/wheatParticleSystem.i3d", self.baseDirectory);
  	    self.pipeParticles[fillType] = currentPS;
      end;
      i = i + 1;
    end;
  end;

 
  if self.isServer then  
    self.chargeTriggers = {};
    i = 0;
    while true do
      local key = string.format(xmlKey .. "chargeTriggers.Trigger(%d)", i);
      local index = getXMLString(xmlFile, key .. "#index");
      if index == nil then
        break;
      end;
      local val = Utils.indexToObject(self.components, index);
      self.chargeTriggers[val] = Utils.getNoNil(getXMLString(xmlFile, key .. "#pipePosition"), "none");

      i = i + 1;
    end;
    for k, v in pairs(self.chargeTriggers) do
      addTrigger(k, "onChargeTrigger", self);
    end;

   
    self.literPerSecond = Utils.getNoNil(getXMLInt(xmlFile, xmlKey .. "literPerSecond#value"), 250);
  end;
  
  self.trappeNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.trappeNode#index"));
  self.inRange = false;
end;


function ChargeSowing:delete() 
  for _, particleSystem in pairs(self.pipeParticles) do
    Utils.deleteParticleSystem(particleSystem);
  end;
  if self.isServer then
    for k, _ in pairs(self.chargeTriggers) do
      removeTrigger(k);
    end;
  end;
end;

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

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


function ChargeSowing:readStream(streamId, connection)
  local i;
  local tableNum;
  local debugNum = 9; 
  local bool; 
  if streamReadBool(streamId) then
    self.isTrailerInRange = true;
    self.sendIsTrailerInRange = self.isTrailerInRange;
    self.trailerToOverload = networkGetObject(streamReadInt32(streamId));
    if self.trailerToOverload then
      self.trailerFound = self.trailerToOverload.rootNode;
    else
      self.isTrailerInRange = false;
    end;
  end; 

  self.isCharging = streamReadBool(streamId);
end;


function ChargeSowing:writeStream(streamId, connection)
  local i = 0;
  local isNotEmpty = false;

 
  streamWriteBool(streamId, self.isTrailerInRange);
  if self.isTrailerInRange then
    streamWriteInt32(streamId, networkGetObjectId(self.trailerToOverload));  
  end;
 
  streamWriteBool(streamId, self.isCharging);
end;


function ChargeSowing:readUpdateStream(streamId, timestamp, connection)
  if connection:getIsServer() then  
      if streamReadBool(streamId) then
        self.isTrailerInRange = true;
        self.trailerToOverload = networkGetObject(streamReadInt32(streamId));
        self.trailerFound = self.trailerToOverload.rootNode;
      else
        self.isTrailerInRange = false;
        self.trailerFound = false;
        self.trailerToOverload = nil;
      end;
  end;
end;


function ChargeSowing:writeUpdateStream(streamId, connection, dirtyMask)
  if not connection:getIsServer() then  
    streamWriteBool(streamId, self.isTrailerInRange);  
    if self.isTrailerInRange then     
        streamWriteInt32(streamId, networkGetObjectId(self.trailerToOverload));     
    end;
  end;
end;



function ChargeSowing:draw()
    

    if self.isCharging then
      g_currentMission:addExtraPrintText(g_i18n:getText("EXTRA_HELP"));
    else
      if self.isTrailerInRange and self.fillLevel <= 0.0 then
        g_currentMission:addExtraPrintText( (g_i18n:getText("ChargeSowing_isEmpty")):format(self.ULWName));
      elseif self.isTrailerInRange and self.trailerToOverload:allowFillType(self.currentFillType, true) then
        g_currentMission:addExtraPrintText(g_i18n:getText("EXTRA_HELP"), InputBinding.IMPLEMENT_EXTRA);
      end;
    end;
 
 if self.chargeOverlay ~= nil and self.isCharging == false and self.inRange and self.isTrailerInRange and self.fillLevel > 0 then
    self.chargeOverlay:render();
  end; 
  
  
 -- if self.chargeOverlay ~= nil and self.isCharging == false and self.isTrailerInRange and self.fillLevel > 0 then
    --self.chargeOverlay:render();
  --end;  
 
end;


function ChargeSowing:updateTick(dt)
self:handleChargeTriggers();
self:handlePipeParticles();

if self.trappeNode ~= nil then     
		if g_currentMission.player ~= nil then
		  local nearestDistance = 3; 
		  local px, py, pz = getWorldTranslation(self.trappeNode);

		  local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);

		  local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);

		  if distance < nearestDistance then                    
		    self.inRange = true;

		  else

         	    self.inRange = false;

		  end;

		end;

else

 self.inRange = false;

end;


end;

function ChargeSowing:update(dt)
if self.isTrailerInRange then
    if self.isCharging and self.inRange then
      g_currentMission:addHelpButtonText( g_i18n:getText("ChargeSowing_chargeOff"), InputBinding.IMPLEMENT_EXTRA);	  
    else
      if self.inRange and self.fillLevel <= 0.0 then
        g_currentMission:addExtraPrintText( (g_i18n:getText("ChargeSowing_isEmpty")):format(self.ULWName));
      elseif self.inRange and self.trailerToOverload:allowFillType(self.currentFillType, true) then
        g_currentMission:addHelpButtonText( g_i18n:getText("ChargeSowing_chargeOn"), InputBinding.IMPLEMENT_EXTRA);		
      end;
    end;

--if self.isClient and self.isSelected and self:getIsActiveForInput()  then
 --if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
    -- self.isCharging = not self.isCharging;      
 --end;
--end;

if self.inRange then
 if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
     self.isCharging = not self.isCharging;      
 end;
end;

end;




if self.isCharging then
    self:setAnimationTime(2, self.animationParts[2].animDuration);
else
    self:setAnimationTime(2, self.animationParts[2].startPosition);  
end; 
     
if self.isCharging then
 if self.isTrailerInRange and self.attacherVehicle ~= nil then
    if not self.trailerToOverload:allowFillType(self.currentFillType, true) then
         self.isCharging = false;
    end;
 else
    self.isCharging = false;
 end;
end;
 
 
if self.sendIsCharging ~= self.isCharging then
    self.sendIsCharging = self.isCharging;
    ChargeSowingChargeEvent:sendEvent(self, self.isCharging);
end;

if self.isClient then
          if self.currentFillType ~= self.fillType or self.fillLevel <= 0 then
                  Utils.setEmittingState(self.pipeParticles[self.currentFillType], false);
          end
end     

 
self:handleGrainTransfer(dt);
self:handlePipeParticles();
end;

function ChargeSowing:handleGrainTransfer(dt)
  if self.literPerSecond ~= nil and self.isServer and self.isCharging and self.fillLevel > 0 then    
    if self.trailerToOverload == nil or self.trailerToOverload.fillLevel == self.trailerToOverload.capacity or self.fillLevel <= 0.0 then      
      self.isCharging = false;        
    else        
      local deltaLevel = self.literPerSecond * (dt/1000);
      deltaLevel = math.min(deltaLevel, self.trailerToOverload.capacity - self.trailerToOverload.fillLevel);
      self.trailerToOverload:setFillLevel(self.trailerToOverload.fillLevel + math.min(deltaLevel, self.fillLevel), self.currentFillType);
      self:setFillLevel(self.fillLevel - math.min(deltaLevel, self.fillLevel), self.currentFillType);
      Utils.setEmittingState(self.pipeParticles[self.currentFillType], true);     
    end;
  else      
      Utils.setEmittingState(self.pipeParticles[self.currentFillType], false);  
  end;
end;

function ChargeSowing:handleChargeTriggers()
  if self.isServer and self.attacherVehicle ~= nil then
    local isTrailerInRange = false;
    local trailerFound = false;
    local trailerToOverload;
    for k, v in pairs(self.chargeTriggerList) do     
        isTrailerInRange = true;
        trailerFound = v.otherId;
        trailerToOverload = g_currentMission.nodeToVehicle[v.otherId]; 
    end;

    
    if self.trailerFound ~= trailerFound then
      self.isTrailerInRange = isTrailerInRange;
      self.trailerFound = trailerFound;
      self.trailerToOverload = trailerToOverload;
    end;
  elseif self.isServer and self.isTrailerInRange then
    self.isTrailerInRange = false;
    self.trailerFound = false;
    self.trailerToOverload = nil;
  end;
end;

function ChargeSowing:onChargeTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
  if (onStay or onEnter) and self.chargeTriggers[triggerId] then
    if self.chargeTriggerList[triggerId] == nil then
      if g_currentMission.nodeToVehicle[otherId] ~= nil then
        self.chargeTriggerList[triggerId] = {};
        self.chargeTriggerList[triggerId].counter = 1;
        self.chargeTriggerList[triggerId].otherId = otherId;
        self.chargeTriggerList[triggerId].pipePosition = self.chargeTriggers[triggerId];
      end;
    else
      self.chargeTriggerList[triggerId].counter = self.chargeTriggerList[triggerId].counter + 1;
    end;
  elseif onLeave then
    if self.chargeTriggerList[triggerId] then
      if self.chargeTriggerList[triggerId].counter == 1 then
        self.chargeTriggerList[triggerId] = nil;
      else
        self.chargeTriggerList[triggerId].counter = self.chargeTriggerList[triggerId].counter - 1;
      end;
    end;
  end;
end;

function ChargeSowing:handlePipeParticles()
  if self.isCharging then
    if not self.lastFillType then
      self.lastFillType = self.currentFillType;
    end;    
  elseif not self.isCharging then   
    self.lastFillType = nil;
  end;
end;

ChargeSowingChargeEvent = {};
ChargeSowingChargeEvent_mt = Class(ChargeSowingChargeEvent, Event);

InitEventClass(ChargeSowingChargeEvent, "ChargeSowingChargeEvent");

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

function ChargeSowingChargeEvent:new(object, isCharging)
  local self = ChargeSowingChargeEvent:emptyNew();
  self.object = object;
  self.isCharging = isCharging;
  return self;
end;

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

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

function ChargeSowingChargeEvent:run(connection)
  self.object.isCharging = self.isCharging;
  self.object.sendIsCharging = self.isCharging;
  if not connection:getIsServer() then
    g_server:broadcastEvent(ChargeSowingChargeEvent:new(self.object, self.isCharging), nil, connection, self.object);
  end;
end;

function ChargeSowingChargeEvent:sendEvent(object, isCharging, noEventSend)
  if noEventSend == nil or noEventSend == false then
    if g_server ~= nil then
      g_server:broadcastEvent(ChargeSowingChargeEvent:new(object, isCharging), nil, nil, object);
    else
      g_client:getServerConnection():sendEvent(ChargeSowingChargeEvent:new(object, isCharging));
    end;
  end;
end;

