-- NI Modding
--
-- author  	Henly20 
-- date  	03-02-2013.
-- ni_modding@hotmail.com
-- http://nimodding.wordpress.com


PUH = {};

function PUH.prerequisitesPresent(specializations)
    return true;
end;

function PUH:load(xmlFile)
	self.setRotationMax1 = SpecializationUtil.callSpecializationsFunction("setRotationMax1");
	self.setRotationMax2 = SpecializationUtil.callSpecializationsFunction("setRotationMax2");
	self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
	
	local rotationPUHNode1 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rotationPUH1#index"));
		if rotationPUHNode1 ~= nil then
        self.rotationPUH1 = {};
        self.rotationPUH1.node = rotationPUHNode1;

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

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

        self.rotationPUH1.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPUH1#rotTime"), 2)*1000;
        self.rotationPUH1.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPUH1#touchRotLimit"), 10));
    end;	
	local rotationPUHNode2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rotationPUH2#index"));
		if rotationPUHNode2 ~= nil then
        self.rotationPUH2 = {};
        self.rotationPUH2.node = rotationPUHNode2;

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

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

        self.rotationPUH2.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPUH2#rotTime"), 2)*1000;
        self.rotationPUH2.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPUH2#touchRotLimit"), 10));
    end;	
	local translationAttacherNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.translationAttacher#index"));
		if translationAttacherNode ~= nil then
        self.translationAttacher = {};
        self.translationAttacher.node = translationAttacherNode;
        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.translationAttacher#minTrans"));
        self.translationAttacher.minTrans = {};
        self.translationAttacher.minTrans[1] = Utils.getNoNil(x, 0);
        self.translationAttacher.minTrans[2] = Utils.getNoNil(y, 0);
        self.translationAttacher.minTrans[3] = Utils.getNoNil(z, 0);

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

        self.translationAttacher.transTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.translationAttacher#transTime"), 2)*1000;
        self.translationAttacher.touchTransLimit = Utils.getNoNil(getXMLString(xmlFile, "vehicle.translationAttacher#touchTransLimit"), 10);
    end;	

	self.rotationMax1 = false;	
	self.rotationMax2 = false;	
	self.translationAttacherMax = false;
	self.PUHActive = true;
	self.drawbarActive = false;
	self.drawbarAvailable = true;
	self.liftarmsActive = false;
	self.PUHAllActive = false;
	self.implementAdded = false;	
	self.isSelectable = true;	
	
	self.backAttacherJoint = {};
	self.backAttacherJoint.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.trailerAttacherJoints#node"));
	
	self.drawbar = {};
	self.drawbar[1] = Utils.indexToObject(self.components,getXMLString(xmlFile,"vehicle.drawbar#index"));
	self.drawbar[2] = Utils.indexToObject(self.components,getXMLString(xmlFile,"vehicle.drawbar#index1"));
	
	setVisibility(self.drawbar[1], false);
	setVisibility(self.drawbar[2], true); 	
	
	self.toplink = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.topLink#index"));
	self.highhitch = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.highHitch#index"));
 	setVisibility((self.toplink), false);
 	setVisibility((self.highhitch), true);

end;

function PUH:delete()
end;

function PUH:readStream(streamId, connection)
	local state = streamReadBool(streamId);
	self:setRotationMax1(state, true);
	local state2 = streamReadBool(streamId);
	self:setRotationMax2(state2, true);
end;

function PUH:writeStream(streamId, connection)
	  streamWriteBool(streamId,self.rotationMax1);
	  streamWriteBool(streamId,self.rotationMax2);
end;

function PUH:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		local isTurnedOn = Utils.getNoNil(getXMLBool(xmlFile, key.."#isTurnedOn"), true);
		if isTurnedOn ~= nil then
			self:setIsTurnedOn(isTurnedOn);
		end;
	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function PUH:getSaveAttributesAndNodes(nodeIdent)
	local attributes = ' ';
	
	local mystring = 'isTurnedOn="' .. tostring(self.isTurnedOn) ..'"';	
	attributes = attributes .. mystring;
	
    local node = nil;
	return attributes, node;	
end;

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

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

function PUH:update(dt)


	if not self:getIsActive() then
		if self.drawbarInRange and self.drawbarAvailable and not self.rotationMax1 then		
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
				  self:setIsTurnedOn(not self.isTurnedOn);
			end;
			if self.drawbarAvailable then
				if self.isTurnedOn then
					g_currentMission:addHelpButtonText(string.format(g_i18n:getText("drawbar_remove"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
				else
					g_currentMission:addHelpButtonText(string.format(g_i18n:getText("drawbar_add"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
				end;
			end;
		end;
	end;

    if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
		if self.PUHActive and not self.drawbarActive and not self.liftarmsActive then
			if InputBinding.hasEvent(InputBinding.PUH) then	
				self:setRotationMax1(not self.rotationMax1);
				self:setRotationMax2(not self.rotationMax2);			
			end;
		end;
		if not self.PUHAllActive then
			if InputBinding.hasEvent(InputBinding.LIFTARMS) then	
				self:setRotationMax2(not self.rotationMax2);
			end;
		end;		
	end;
end;

function PUH:updateTick(dt)
	if g_currentMission.player ~= nil then
		local nearestDistance = 1.8;
		local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);		
		local px, py, pz = getWorldTranslation(self.rotationPUH1.node); 
		local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);	
		if distance < nearestDistance then
			self.drawbarInRange = true; 
		else
			self.drawbarInRange = false; 
		end;
	end;

    if self:getIsActive() then
		if self.rotationMax2 and not self.PUHAllActive then
			self.liftarmsActive = true;
		else
			self.liftarmsActive = false;	
		end;	
		if self.rotationMax1 then
			self.PUHAllActive = true;
		else
			self.PUHAllActive = false;	
		end;
		if self.implementAdded then
			self.PUHActive = false;
		else
			self.PUHActive = true;
		end;
		if not self.rotationMax1 then
			self.PUHAllActive = false;		
		end
		if self.rotationMax1 ~= nil then
			local x, y, z = getRotation(self.rotationPUH1.node);
			local rot = {x,y,z};
			local newRot = Utils.getMovedLimitedValues(rot, self.rotationPUH1.maxRot, self.rotationPUH1.minRot, 3, self.rotationPUH1.rotTime, dt, not self.rotationMax1);
			setRotation(self.rotationPUH1.node, unpack(newRot));
		end;
		if self.PUHActive then 
			if self.rotationMax2 ~= nil then
				local x, y, z = getRotation(self.rotationPUH2.node);
				local rot = {x,y,z};
				local newRot = Utils.getMovedLimitedValues(rot, self.rotationPUH2.maxRot, self.rotationPUH2.minRot, 3, self.rotationPUH2.rotTime, dt, not self.rotationMax2);
				setRotation(self.rotationPUH2.node, unpack(newRot));
				setRotation(self.attacherJoints[1].bottomArm.rotationNode, unpack(newRot));
				setRotation(self.backAttacherJoint.node, unpack(newRot));	
			end;
		end;
	end;
    if self:getIsActive() or not self:getIsActive() then		
		if self.translationAttacher.node ~= nil then
			local x, y, z = getTranslation(self.translationAttacher.node);
			local trans = {x,y,z};
			local newTrans = Utils.getMovedLimitedValues(trans, self.translationAttacher.maxTrans, self.translationAttacher.minTrans, 3, self.translationAttacher.transTime*2, dt, not self.translationAttacherMax);
			setTranslation(self.translationAttacher.node, unpack(newTrans));
		end;	
	end;
end;

function PUH:draw()
    if self.isClient then
		if self.PUHActive and not self.isTurnedOn then
			if self.rotationMax1 then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Raise_PUH"), self.typeDesc), InputBinding.PUH);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Lower_PUH"), self.typeDesc), InputBinding.PUH);
			end;
		end;
	end;
end;

function PUH:onEnter()

end;

function PUH:onLeave()

end;

function PUH:setRotationMax1(rotationMax1, noEventSend)
     if noEventSend == nil or noEventSend == false then
          if g_server ~= nil then
              g_server:broadcastEvent(SetRotationEvent:new(self, rotationMax1), nil, nil, self);
          else
              g_client:getServerConnection():sendEvent(SetRotationEvent:new(self, rotationMax1));
          end;
      end;
      self.rotationMax1 = rotationMax1;
end;

function PUH:setRotationMax2(rotationMax2, noEventSend)
     if noEventSend == nil or noEventSend == false then
          if g_server ~= nil then
              g_server:broadcastEvent(SetRotationEvent2:new(self, rotationMax2), nil, nil, self);
          else
              g_client:getServerConnection():sendEvent(SetRotationEvent2:new(self, rotationMax2));
          end;
      end;
      self.rotationMax2 = rotationMax2;

end;

function PUH:setIsTurnedOn(isTurnedOn, noEventSend)
	SetTurnedOnEvent.sendEvent(self, isTurnedOn, noEventSend)
	self.isTurnedOn = isTurnedOn;
 
	if self.drawbarAvailable and not self.rotationMax1 then
		if self.isTurnedOn then
			setVisibility(self.drawbar[1], true);
			setVisibility(self.drawbar[2], false);
			self.translationAttacherMax = true;
			self.drawbarActive = true;
		else
			setVisibility(self.drawbar[1], false);
			setVisibility(self.drawbar[2], true);
			self.translationAttacherMax = false;
			self.drawbarActive = false;	
			self.drawbarAvailable = true;			
		end;	
	end; 
end;

function PUH:validateAttacherJoint(implement, jointDesc, dt)
    return true;

end;

function PUH:attachImplement(implement)
	self.rotationMax10 = false;	
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;
	
	if jointType == Vehicle.JOINTTYPE_IMPLEMENT then
			if jointIndex == 1 then
				setVisibility((self.toplink), true);
				setVisibility((self.highhitch), false);	
				self.PUHActive = false;	
				self.drawbarAvailable = false;
				self:setIsTurnedOn(false);			
				setVisibility(self.drawbar[1], false);
				setVisibility(self.drawbar[2], true);
				self.implementAdded = true;
				self.translationAttacherMax = false;			
				if not self.PUHActive then
					self.rotationMax1 = false;	
				end;
			end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILER then
		if jointIndex == 2 then
			self.PUHActive = false;
			self.drawbarAvailable = false;
			if self.rotationMax1 then
				self.rotationMax1 = false;	
				self.rotationMax2 = false;				
			end;	
		end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILERLOW then
		if jointIndex == 3 then	
			self.PUHActive = true;
			self.drawbarAvailable = false;
			if self.rotationMax1 then
				self.rotationMax1 = false;	
				self.rotationMax2 = false;	
			end;
		end;
	end;
	
end;

function PUH:detachImplement(implementIndex)
	self.rotationMax10 = false;
	local implement = self.attachedImplements[implementIndex];
	local jointIndex = implement.jointDescIndex;
	
	if jointIndex == 1 then
		setVisibility((self.toplink), false);
		setVisibility((self.highhitch), true);
		self.PUHActive = true;
		self.liftarmsActive = false;
		self.PUHAllActive = false;			
		self.drawbarAvailable = true;
		self.drawbarActive = false;			
		self.isTurnedOn = false;			
		self.implementAdded = false;
		if not self.rotationMax1 then
			self.rotationMax2 = false;			
		end;
	elseif jointIndex == 2 then
		self.PUHActive = true;
		self.liftarmsActive = false;
		self.PUHAllActive = false;			
		if not self.rotationMax1 then
			self.rotationMax2 = false;	
		end;
		self.drawbarAvailable = true;
	elseif jointIndex == 3 then
		self.PUHActive = true;
		self.liftarmsActive = false;
		if self.rotationMax1 then
			self.drawbarAvailable = true;
			self.PUHAllActive = true;	
		else
			self.drawbarAvailable = true;
			self.PUHAllActive = false;			
		end;
	end;
end;

SetRotationEvent = {};
SetRotationEvent_mt = Class(SetRotationEvent, Event);
 
InitEventClass(SetRotationEvent, "SetRotationEvent");

function SetRotationEvent:emptyNew()
      local self = Event:new(SetRotationEvent_mt);
      self.className="SetRotationEvent";
      return self;
end;
 
function SetRotationEvent:new(object, rotationMax1)
     local self = SetRotationEvent:emptyNew()
     self.object = object;
     self.rotationMax1 = rotationMax1;
      return self;
end;

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

function SetRotationEvent:run(connection)
	if self.object ~= nil then 
		self.object:setRotationMax1(self.rotationMax1, true);
	end;
     if not connection:getIsServer() then
          g_server:broadcastEvent(SetRotationEvent:new(self.object, self.rotationMax1), nil, connection, self.object);
     end;
end;

SetRotationEvent2 = {};
SetRotationEvent2_mt = Class(SetRotationEvent2, Event);
 
InitEventClass(SetRotationEvent2, "SetRotationEvent2");

function SetRotationEvent2:emptyNew()
      local self = Event:new(SetRotationEvent2_mt);
      self.className="SetRotationEvent2";
      return self;
end;
 
function SetRotationEvent2:new(object, rotationMax2)
     local self = SetRotationEvent2:emptyNew()
     self.object = object;
     self.rotationMax2 = rotationMax2;
      return self;
end;

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

function SetRotationEvent2:run(connection)
	if self.object ~= nil then 
		self.object:setRotationMax2(self.rotationMax2, true);
	end;
     if not connection:getIsServer() then
          g_server:broadcastEvent(SetRotationEvent2:new(self.object, self.rotationMax2), nil, connection, self.object);
     end;
end;