--
-- Albutt Dung Grab
--
-- @author    henly20 - LS-UK_info
-- @date      11-8-2011
--
-- edited by PeterJ - LS-UK_info


albuttDgrab = {};

function albuttDgrab.prerequisitesPresent(specializations)
	local newShovelSpec = SpecializationUtil.getSpecialization("pdlc_dlcPack2.newShovel");	
	if newShovelSpec ~= nil then
		table.insert(specializations, SpecializationUtil.getSpecialization("fillable"));
		table.insert(specializations, newShovelSpec);
	else
		table.insert(specializations, SpecializationUtil.getSpecialization("shovel"));
	end;

	return true;
end;

function albuttDgrab:load(xmlFile)

	self.setRotationGrab = SpecializationUtil.callSpecializationsFunction("setRotationGrab");

	local rotationGrabNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rotationGrab#index"));
		if rotationGrabNode ~= nil then
        self.rotationGrab = {};
        self.rotationGrab.node = rotationGrabNode;

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

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

        self.rotationGrab.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationGrab#rotTime"), 2)*1000;
        self.rotationGrab.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationGrab#touchRotLimit"), 10));
    end;
	
	self.rotationGrabMax = false;
		
	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;	
end;

function albuttDgrab:delete()

end;

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

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

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

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

function albuttDgrab:update(dt)

	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
			self:setRotationGrab(not self.rotationGrabMax);
		end;
	end;
end;

function albuttDgrab:updateTick(dt)
    if self:getIsActive() then
		if self.rotationGrab ~= nil then
			local x, y, z = getRotation(self.rotationGrab.node);
			local rot = {x,y,z};
			local newRot = Utils.getMovedLimitedValues(rot, self.rotationGrab.maxRot, self.rotationGrab.minRot, 3, self.rotationGrab.rotTime, dt, not self.rotationGrabMax);
			setRotation(self.rotationGrab.node, unpack(newRot));
		end;
		
		if newShovelSpec ~= nil then
			if self.fillLevel == self.capacity then
				if self.rotationGrabMax then
					self.autoClose = true;
				else
					self.autoClose = false;
					self.automaticOn = false;
				end;
			end;			
			if self.automaticOn then
				if self.autoClose then
					self:setRotationGrab(not self.rotationGrabMax);
				end;
			end;
			if self.fillLevel <= 0 then
				self.automaticOn = true;
				self.autoClose = false;
			end;
		else
			-- auto close/open --
			if self.manureIsFilled then
				if self.rotationGrabMax then
					self.autoClose = true;
					self.autoOpen = false;
				else
					self.autoClose = false;
					self.automaticOn = false;
				end;
				self.autoOpenON = true;
				self.autoOpen = false;
			else
				self.automaticOn = true;
				self.autoClose = false;
				if not self.rotationGrabMax then
					self.autoOpen = true;
				else
					self.autoOpen = false;
					self.autoOpenON = false;
				end;
			end;			

			if (self.automaticOn and self.autoClose) or (self.autoOpenON and self.autoOpen) then
				self:setRotationGrab(not self.rotationGrabMax);
			end;
		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 albuttDgrab:draw()

	if self.rotationGrabMax then
		g_currentMission:addHelpButtonText(g_i18n:getText("Close"), InputBinding.IMPLEMENT_EXTRA2);
	else
		g_currentMission:addHelpButtonText(g_i18n:getText("Open"), InputBinding.IMPLEMENT_EXTRA2);
	end;
end;

function albuttDgrab:onDetach()
	if self.deactivateOnDetach then
        albuttDgrab.onDeactivate(self);
    end;
end;

function albuttDgrab:toggleTipState()
end;

function albuttDgrab:onDeactivate()
end;

function albuttDgrab: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 albuttDgrab:setRotationGrab(rotationGrabMax, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetRotationEventShovel:new(self, rotationGrabMax), nil, nil, self);
		else
			g_client:getServerConnection():sendEvent(SetRotationEventShovel:new(self, rotationGrabMax));
		end;
	end;
	self.rotationGrabMax = rotationGrabMax;
end;

SetRotationEventShovel = {};
SetRotationEventShovel_mt = Class(SetRotationEventShovel, Event);
 
InitEventClass(SetRotationEventShovel, "SetRotationEventShovel");

function SetRotationEventShovel:emptyNew()
      local self = Event:new(SetRotationEventShovel_mt);
      self.className="SetRotationEventShovel";
      return self;
end;
 
function SetRotationEventShovel:new(object, rotationGrabMax)
     local self = SetRotationEventShovel:emptyNew()
     self.object = object;
     self.rotationGrabMax = rotationGrabMax;
      return self;
end;

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

function SetRotationEventShovel:run(connection)
     self.object:setRotationGrab(self.rotationGrabMax, true);
     if not connection:getIsServer() then
          g_server:broadcastEvent(SetRotationEventShovel:new(self.object, self.rotationGrabMax), nil, connection, self.object);
     end;
end;