--
-- hightip

-- Specialization Bressel and Lade 1850 l light cargo shovel --
-- edit by Defender

-- edit by henly20 Ls-uk-info 11-8-2011

hightip = {};



function hightip.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Trailer, specializations) and SpecializationUtil.hasSpecialization(Fillable, specializations);
end;

function hightip:load(xmlFile)
	self.setRotationShovel = SpecializationUtil.callSpecializationsFunction("setRotationShovel");
     self.tipReferencePoint = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipReferencePoint#index"));
      if self.tipReferencePoint == nil then
          self.tipReferencePoint = self.components[1].node;
      end;
	  
	local rotationShovelNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rotationShovel#index"));
		if rotationShovelNode ~= nil then
        self.rotationShovel = {};
        self.rotationShovel.node = rotationShovelNode;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationShovel#minRot"));
        self.rotationShovel.minRot = {};
        self.rotationShovel.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationShovel.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationShovel.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationShovel#maxRot"));
        self.rotationShovel.maxRot = {};
        self.rotationShovel.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationShovel.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationShovel.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationShovel.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationShovel#rotTime"), 2)*1000;
        self.rotationShovel.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationShovel#touchRotLimit"), 10));
    end;
	
	self.rotationShovelMax = false;
	
	self.fallOut = false;
	self.fallOut2 = false;
	self.implementFallOut = true;
	self.isShovel = true;
	
	self.setHydraulicDirection = SpecializationUtil.callSpecializationsFunction("setHydraulicDirection");
	
	local hydraulicsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.hydraulics#count"), 0);	
	self.hydraulics = {};	
	for i=1, hydraulicsCount do
		local hydraulicName = string.format("vehicle.hydraulics.hydraulic%d", i);		
		self.hydraulics[i] = {};		
		self.hydraulics[i].node = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#index"));
		self.hydraulics[i].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punch"));
		self.hydraulics[i].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punchFixpoint"));
		self.hydraulics[i].fixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));	
		local xUp, yUp, zUp = Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, hydraulicName .. "#upVectors"),"0 1 0"));
		self.hydraulics[i].upVectors = {xUp, yUp, zUp};
		
		local ax, ay, az;		
		if self.hydraulics[i].punch ~= nil then
			ax, ay, az = getWorldTranslation(self.hydraulics[i].punch);
		else
			ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
		end;
		if self.hydraulics[i].translationPunch ~= nil then
			local bx, by, bz = getWorldTranslation(self.hydraulics[i].translationPunch);		
			self.hydraulics[i].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
		end;
	end;
	self.setHydraulicTime = 30;
	self.fillLevel = 0;	
end;

function hightip:delete()

end;

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

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

function hightip:readStream(streamId, connection)
     self.rotationShovelMax = streamReadBool(streamId);
     if self.rotationShovel ~= nil then
          local x = streamReadFloat32(streamId);
          local y = streamReadFloat32(streamId);
          local z = streamReadFloat32(streamId);
         setRotation(self.rotationShovel.node, x, y, z);
      end;

end;
  
function hightip:writeStream(streamId, connection)
      streamWriteBool(streamId, self.rotationShovelMax);
		if self.rotationShovel ~= nil then
          local x, y, z = getRotation(self.rotationShovel.node);
          streamWriteFloat32(streamId, x);
          streamWriteFloat32(streamId, y);
          streamWriteFloat32(streamId, z);
      end;
end;

function hightip:update(dt)

      if self:getIsActiveForInput() then

          if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
				self:setRotationShovel(not self.rotationShovelMax);
          end;

     end;

end;

function hightip:updateTick(dt)
    if self:getIsActive() then
		self.fallOut2 = false;
		  if self.attacherVehicle ~= nil then
				self.fallOut2 = false;
				local x,y,z = localDirectionToWorld(self.tipReferencePoint, 0,0,1);
				if y < -0.5 or self.rotationShovelMax then
					self.fallOut = true;
				else
					self.fallOut = false;
				end;
				self.tiltangle = y;
				if self.rotationShovelMax then
				y = -0.5;
				end;

			end;
			if self.fallOut and self.implementFallOut  then
				self:setFillLevel(self.fillLevel, self.currentFillType);
				local nearestDistance = 5.0;
				local px, py, pz = getWorldTranslation(self.tipReferencePoint);
				for i=1, table.getn(g_currentMission.attachables) do
			  local vx, vy, vz = getWorldTranslation(g_currentMission.attachables[i].rootNode);
					local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
					if distance < nearestDistance then
						local attachable = g_currentMission.attachables[i];		
						if attachable.fillTypes ~= nil and attachable.setFillLevel ~= nil and attachable.fillLevel ~= nil and attachable ~= self then
							if self.currentFillType == attachable.currentFillType or attachable.currentFillType == FruitUtil.FRUITTYPE_UNKNOWN then
								if attachable.fillLevel < attachable.capacity  and self.fillLevel > 1 then							
									local deltaLevel = (self.tiltangle*self.tiltangle)*(self.capacity/200)*dt							
									local fillDelta = math.min(deltaLevel, self.fillLevel)
									self:setFillLevel(self.fillLevel - fillDelta, self.currentFillType);
									attachable:setFillLevel(attachable.fillLevel + fillDelta, self.currentFillType);
									self.fallOut2 = self.fillLevel>0 and fillDelta>0;						
								end; 
							end;
						end;
					end;
				end;
				
			end;
				
			if self.fillLevel == 0 then
				self.currentFillType = FruitUtil.FRUITTYPE_UNKNOWN;
			end;
			Utils.setEmittingState(self.dischargeParticleSystems[self.currentFillType], self.fallOut2);

		if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_CLOSING or self.tipState == Trailer.TIPSTATE_OPEN then
				self:setRotationShovel(false);
				Utils.setEmittingState(self.dischargeParticleSystems[self.currentFillType]);
		self.fallOut = true;
		self.fallOut2 = true;
		self.implementFallOut = true;
		self.isShovel = false;
		else
		self.fallOut = false;
		self.fallOut2 = false;
		self.implementFallOut = true;
		self.isShovel = true;
		end;

		if self.rotationShovel ~= nil then
			local x, y, z = getRotation(self.rotationShovel.node);
			local rot = {x,y,z};
			local newRot = Utils.getMovedLimitedValues(rot, self.rotationShovel.maxRot, self.rotationShovel.minRot, 3, self.rotationShovel.rotTime, dt, not self.rotationShovelMax);
			setRotation(self.rotationShovel.node, unpack(newRot));
		end;
		
		if self:getIsActive() then			
			self.setHydraulicTime = 30;	
		end;

		if self.setHydraulicTime > 0 then
			for k,v in pairs(self.hydraulics) do 
				self:setHydraulicDirection(k);
			end;
			self.setHydraulicTime = self.setHydraulicTime - 1;
		end;
	end;
end;

function hightip:draw()
	if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_CLOSING or self.tipState == Trailer.TIPSTATE_OPEN then
	g_currentMission:addExtraPrintText("   ");	
	else
	if self.rotationShovelMax then
		g_currentMission:addHelpButtonText(g_i18n:getText("LowerBucket"), InputBinding.IMPLEMENT_EXTRA2);
	else
		g_currentMission:addHelpButtonText(g_i18n:getText("TipBucket"), InputBinding.IMPLEMENT_EXTRA2);
	end;
	end
end;

function hightip:onDetach()

   if self.deactivateOnDetach then
        hightip.onDeactivate(self);
    end;
end;

function hightip:toggleTipState()
end;

function hightip:onDeactivate()
    self.fallOut = false;
end;

function hightip:setHydraulicDirection(index)
	local hydraulic = self.hydraulics[index];

	if hydraulic.fixPoint ~= nil then
		local ax, ay, az = getWorldTranslation(hydraulic.node);
		local bx, by, bz = getWorldTranslation(hydraulic.fixPoint);
		local x, y, z = worldDirectionToLocal(getParent(hydraulic.node), bx-ax, by-ay, bz-az);
		local xUp, yUp, zUp = unpack(hydraulic.upVectors);
		setDirection(hydraulic.node, x, y, z, xUp, yUp, zUp);
		if hydraulic.punch ~= nil then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setTranslation(hydraulic.punch, 0, 0, distance-hydraulic.punchDistance);
		end;
	end;
end;


function hightip:setRotationShovel(rotationShovelMax, noEventSend)
     if noEventSend == nil or noEventSend == false then
          if g_server ~= nil then
              g_server:broadcastEvent(SetRotationEventShovel1:new(self, rotationShovelMax), nil, nil, self);
          else
              g_client:getServerConnection():sendEvent(SetRotationEventShovel1:new(self, rotationShovelMax));
          end;
      end;
      self.rotationShovelMax = rotationShovelMax;
end;

SetRotationEventShovel1 = {};
SetRotationEventShovel1_mt = Class(SetRotationEventShovel1, Event);
 
InitEventClass(SetRotationEventShovel1, "SetRotationEventShovel11");

function SetRotationEventShovel1:emptyNew()
      local self = Event:new(SetRotationEventShovel1_mt);
      self.className="SetRotationEventShovel1";
      return self;
end;
 
function SetRotationEventShovel1:new(object, rotationShovelMax)
     local self = SetRotationEventShovel1:emptyNew()
     self.object = object;
     self.rotationShovelMax = rotationShovelMax;
      return self;
end;

function SetRotationEventShovel1:readStream(streamId, connection)
      local id = streamReadInt32(streamId);
     self.rotationShovelMax = streamReadBool(streamId);
     self.object = networkGetObject(id);
      self:run(connection);
end;
 
function SetRotationEventShovel1:writeStream(streamId, connection)
      streamWriteInt32(streamId, networkGetObjectId(self.object));
      streamWriteBool(streamId, self.rotationShovelMax);
end;

function SetRotationEventShovel1:run(connection)
     self.object:setRotationShovel(self.rotationShovelMax, true);
     if not connection:getIsServer() then
          g_server:broadcastEvent(SetRotationEventShovel1:new(self.object, self.rotationShovelMax), nil, connection, self.object);
     end;
end;