--
-- Lanes
-- Specialization for Lanes
--
-- @author    Manuel Leithner (SFM-Modding)
-- @version   v2.0
-- @date      08/11/11
-- @history:  v1.0 - Initial version
--            v1.1 - Edit by JoXXer (BJR-Modding) to add functionality to run down grass
--            v2.0 - Modified heavily by Decker_MMIV (FMC) to run down everything!
--                   Unfortunately this may cause massive lag in a multiplayer game, unless played only in local-network (LAN).
--

Lanes = {};

function Lanes.prerequisitesPresent(specializations)
  --return SpecializationUtil.hasSpecialization(Steerable, specializations);
  return true
end;

function Lanes:load(xmlFile)
end;

function Lanes:delete()
end;

function Lanes:readStream(streamId, connection)
end;

function Lanes:writeStream(streamId, connection)
end;

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

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

function Lanes:update(dt)
end;

function Lanes:updateTick(dt)
  if self.isServer and self:getIsActive() then
    -- Only "destroy foliage" when vehicle is actually moving...
    if self.movingDirection ~= 0 then 
      local cuttingAreasSend = {};
      --
      --if true then
        -- Use the defined wheels, and calculate some "cuttingArea" for each of them.
        -- Some code-fragment inspired from wheellanes.lua by Blacky_BPG
        for i=1,table.getn(self.wheels) do
          if self.wheels[i].hasGroundContact then
            local radius = self.wheels[i].radius;
            if radius ~= nil then
              local x,y,z = getWorldTranslation(self.wheels[i].repr);
              x = x - (radius / 4);
              z = z - (radius / 4);
              local x1 = x + (radius / 2);
              local z1 = z;
              local x2 = x;
              local z2 = z + (radius / 2);          
              table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
            end
          end
        end
      --else
      --  -- Use "cuttingAreas" directly - though this may NOT work with equipment/tools.
      --  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);
      --      table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
      --    end;
      --  end;
      --end
      
      
      if table.getn(cuttingAreasSend) > 0 then
        LanesEvent.runLocally(cuttingAreasSend);
        -- NOTE! This is going to be very "chatty" in multiplayer, and therefore may cause massive lag!
        g_server:broadcastEvent(LanesEvent:new(cuttingAreasSend));
      end;
    end;
  end;
end;

function Lanes:draw()
end;

----
----
----

-- Lanes Event-class
LanesEvent = {};
LanesEvent_mt = Class(LanesEvent, Event);

InitEventClass(LanesEvent, "LanesEvent");

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

function LanesEvent:new(cuttingAreas)
  local self = LanesEvent:emptyNew()
  assert(table.getn(cuttingAreas) > 0);
  self.cuttingAreas = cuttingAreas;
  return self;
end;

function LanesEvent:readStream(streamId, connection)
  local numAreas = streamReadUIntN(streamId, 4);

  local refX = streamReadFloat32(streamId);
  local refY = streamReadFloat32(streamId);
  local values = Utils.readCompressed2DVectors(streamId, refX, refY, numAreas*3-1, 0.01, true);

  LanesEvent.destroyFoliageLayers(numAreas,values)
end;

function LanesEvent:writeStream(streamId, connection)
  local numAreas = table.getn(self.cuttingAreas);
  streamWriteUIntN(streamId, numAreas, 4);

  local refX, refY;
  local values = {};
  for i=1, numAreas do
    local d = self.cuttingAreas[i];
    if i==1 then
      refX = d[1];
      refY = d[2];
      streamWriteFloat32(streamId, d[1]);
      streamWriteFloat32(streamId, d[2]);
    else
      table.insert(values, {x=d[1], y=d[2]});
    end;
    table.insert(values, {x=d[3], y=d[4]});
    table.insert(values, {x=d[5], y=d[6]});
  end;
  assert(table.getn(values) == numAreas*3 - 1);
  Utils.writeCompressed2DVectors(streamId, refX, refY, values, 0.01);
end;

function LanesEvent:run(connection)
  print("Error: Do not run LanesEvent locally");
end;

function LanesEvent.runLocally(cuttingAreas)
  local numAreas = table.getn(cuttingAreas);
  local refX, refY;
  local values = {};
  for i=1, numAreas do
    local d = cuttingAreas[i];
    if i==1 then
      refX = d[1];
      refY = d[2];
    else
      table.insert(values, {x=d[1], y=d[2]});
    end;
    table.insert(values, {x=d[3], y=d[4]});
    table.insert(values, {x=d[5], y=d[6]});
  end;
  assert(table.getn(values) == numAreas*3 - 1);
  local values = Utils.simWriteCompressed2DVectors(refX, refY, values, 0.01, true);
  
  LanesEvent.destroyFoliageLayers(numAreas,values)
end
  
function LanesEvent.destroyFoliageLayers(numAreas,values)  
  for i=1, numAreas do
    local vi = (i-1)*3;
    
    local x,z, widthX,widthZ, heightX,heightZ = Utils.getXZWidthAndHeight(
      nil,
      values[vi+1].x,
      values[vi+1].y,
      values[vi+2].x,
      values[vi+2].y,
      values[vi+3].x,
      values[vi+3].y
    );

    -- Destroy ALL fruits with foliage-layers that allows-seeding, disregarding whatever growth-state they are at.
    local value = 0
    for fruitIndex,fruit in pairs(g_currentMission.fruits) do
      if fruit.id ~= 0 -- fruit must have a foliage-layer id
      and FruitUtil.fruitIndexToDesc[fruitIndex].allowsSeeding -- only destroy fruit that we can actually seed
      then
        setDensityParallelogram(
          fruit.id, -- destination foliage-id
          x, z, widthX, widthZ, heightX, heightZ, -- destination parallelogram
          0, -- destination foliage's channel-start-offset-bit
          g_currentMission.numFruitStateChannels, -- destination foliage's number-of-bits-the-value-affects
          value  -- destination foliage's value-to-set
        );

        --setDensityMaskedParallelogram(
        --  fruit.id, -- destination foliage-id
        --  x, z, widthX, widthZ, heightX, heightZ, -- destination parallelogram
        --  0, -- destination foliage's channel-start-offset-bit
        --  g_currentMission.numFruitStateChannels, -- destination foliage's number-of-bits-the-value-affects
        --  fruit.id, -- source/masked foliage-id
        --  0, -- source/masked foliage's channel-start-offset-bit
        --  g_currentMission.numFruitStateChannels, -- source/masked foliage's number-of-bits-to-mask-against
        --  0  -- destination foliage's value-to-set
        --);
      end
    end
  end;
end;
