--
-- BJR_CoverEdge
--
-- @author  JoXXer
-- @date  	31/10/13
--
-- @history	v1.0 - Initial implementation
--
--

BJR_CoverEdge = {};

function BJR_CoverEdge.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(VariableChamberBaler, specializations);
end;

function BJR_CoverEdge:load(xmlFile)
	self.setHasNet = SpecializationUtil.callSpecializationsFunction("setHasNet");
	self.setHasSpareNet = SpecializationUtil.callSpecializationsFunction("setHasSpareNet");
	-- CoverEdge management --
	self.coverEdge = {};
	
	self.coverEdge.checkString = Utils.getNoNil(getXMLString(xmlFile, "vehicle.coverEdge#checkString"), "CoverEdgePallet");
	
	self.coverEdge.netNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.coverEdge#index"));
	self.coverEdge.spareNetNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.coverEdge#spareIndex"));
	self.coverEdge.rollNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.coverEdge#rollIndex"));
	
	self.coverEdge.capacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.coverEdge#capacity"), 4);
	local minScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.coverEdge#minScale"), 1);
	local scaleDiff = 1 - minScale;
	self.coverEdge.scalePerNet = scaleDiff/self.coverEdge.capacity;
	
	local rollEmptyY = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.coverEdge#rollEmptyY"), 1);
	local transX, transY, transZ = getTranslation(self.coverEdge.rollNode);
	local transDiff = rollEmptyY - transY;
	self.coverEdge.rollTransPerNet = transDiff/self.coverEdge.capacity;
	self.coverEdge.rollStartTrans = {transX, transY, transZ};
	
	self.coverEdge.netLeftCount = self.coverEdge.capacity;
	
	self.coverEdge.isLoaded = true;
	self.coverEdge.hasSpareNet = true;
	self.coverEdge.inRange = false;
	
	self.coverEdge.palletInRange = nil;
end;

function BJR_CoverEdge:delete()
end;

function BJR_CoverEdge:readStream(streamId, connection)
	local hasSpareNet = streamReadBool(streamId);
	self:setHasSpareNet(hasSpareNet, true);
	
    self.coverEdge.netLeftCount = streamReadInt32(streamId);
end;

function BJR_CoverEdge:writeStream(streamId, connection)
    streamWriteBool(streamId, self.coverEdge.hasSpareNet);
	
    streamWriteInt32(streamId, self.coverEdge.netLeftCount);
end;

function BJR_CoverEdge:readUpdateStream(streamId, timestamp, connection)
end;

function BJR_CoverEdge:writeUpdateStream(streamId, connection, dirtyMask)
end;

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

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

function BJR_CoverEdge:update(dt)
	-- Manage key events --
	if self.coverEdge.inRange then
		if not self.coverEdge.isLoaded and (self.doors.rear.isOpen == nil or self.doors.rear.isOpen) then
			if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
				if self.coverEdge.hasSpareNet then
					self:setHasNet(true);
				end;
			end;
		end;
		
		if self.coverEdge.palletInRange ~= nil and (self.doors.rear.isOpen == nil or self.doors.rear.isOpen) then
			if InputBinding.hasEvent(InputBinding.ACTIVATE_OBJECT) then
				if self.coverEdge.hasSpareNet == false and self.coverEdge.palletInRange.rollsLeft > 0 then
					self:setHasSpareNet(true);
					self.coverEdge.palletInRange:removeRoll(self.coverEdge.palletInRange.rollsLeft-1);
				end;
			end;
		end;
	end;
	-- trigger the breakdown --
	if self.coverEdge.netLeftCount <= 0 and self.coverEdge.isLoaded then
		self:setHasNet(false);
	end;
	
	-- Set scale and trans for net roll
	if self.isClient then
		local balesNetted = self.coverEdge.capacity - self.coverEdge.netLeftCount;
		local scaleX, scaleY, scaleZ = getScale(self.coverEdge.netNode);
		local currentScale = 1 - (self.coverEdge.scalePerNet * balesNetted);
		if currentScale ~= scaleY then
			setScale(self.coverEdge.netNode, 1, currentScale, currentScale);
		end;
		
		local transX, transY, transZ = getTranslation(self.coverEdge.rollNode);
		local startX, startY, startZ = unpack(self.coverEdge.rollStartTrans);
		local currentTransY = startY + (self.coverEdge.rollTransPerNet * balesNetted);
		if currentTransY ~= transY then
			setTranslation(self.coverEdge.rollNode, startX, currentTransY, startZ);
		end;
	end;
	-- Display key when in range --
	if self.coverEdge.inRange then
		if not self.coverEdge.isLoaded and (self.doors.rear.isOpen == nil or self.doors.rear.isOpen) then
			if self.coverEdge.hasSpareNet then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("BJR_RELOAD_NET")), InputBinding.IMPLEMENT_EXTRA);
			elseif self.coverEdge.palletInRange == nil then
				g_currentMission:addWarning(g_i18n:getText("BJR_NO_SPARE_NET_1") .. "\n" .. g_i18n:getText("BJR_NO_SPARE_NET_2"), 0.07+0.022, 0.019+0.029);
			end;
		end;
		
		if self.coverEdge.palletInRange ~= nil and (self.doors.rear.isOpen == nil or self.doors.rear.isOpen) then
			if self.coverEdge.hasSpareNet == false and self.coverEdge.palletInRange.rollsLeft > 0 then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("BJR_RELOAD_SPARE_NET")), InputBinding.ACTIVATE_OBJECT);
			end;
		end;
	end;
end;

function BJR_CoverEdge:updateTick(dt)
	if self.attacherVehicle and g_currentMission.player ~= nil then
		-- Getting the distance between the player and the implement
		local nearestDistance = 4.0; --max distance allowed
		local px, py, pz = getWorldTranslation(self.rootNode);
		if self.doors.rear.rangeIndex then
			nearestDistance = 2.0;
			px, py, pz = getWorldTranslation(self.doors.rear.rangeIndex);
		end;
		
		local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);
		local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
		if distance < nearestDistance then
			self.coverEdge.inRange = true;
		else
			self.coverEdge.inRange = false;
		end;
	end;
end;

function BJR_CoverEdge:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local hasSpareNet = Utils.getNoNil(getXMLBool(xmlFile, key .. "#hasSpareNet"), true);
	self:setHasSpareNet(hasSpareNet, true);
	
    return BaseMission.VEHICLE_LOAD_OK;
end;

function BJR_CoverEdge:getSaveAttributesAndNodes(nodeIdent)
    local attributes = 'hasSpareNet="' .. tostring(self.coverEdge.hasSpareNet) ..'"';
    return attributes, nil;
end;

function BJR_CoverEdge:setHasNet(isLoaded, noEventSend)
	SetHasNetEvent.sendEvent(self, isLoaded, noEventSend);
	if isLoaded then
		self.coverEdge.netLeftCount = self.coverEdge.capacity;
		setScale(self.coverEdge.netNode, 1, 1, 1);
		setTranslation(self.coverEdge.rollNode, unpack(self.coverEdge.rollStartTrans));
		setVisibility(self.coverEdge.netNode, true);
		self:setHasSpareNet(false, true);
	else
		setVisibility(self.coverEdge.netNode, false);
	end;
	
	self.coverEdge.isLoaded = isLoaded;
end;

function BJR_CoverEdge:setHasSpareNet(hasSpare, noEventSend)
	SetHasSpareNetEvent.sendEvent(self, hasSpare, noEventSend);
	
	setVisibility(self.coverEdge.spareNetNode, hasSpare);
	self.coverEdge.hasSpareNet = hasSpare;
end;

function BJR_CoverEdge:draw()
	if not self.coverEdge.isLoaded then
		 g_currentMission:addWarning(g_i18n:getText("BJR_OUT_OF_NET_1") .. "\n" .. g_i18n:getText("BJR_OUT_OF_NET_2"), 0.07+0.022, 0.019+0.029);
	end;
--~ 	setTextBold(true);
--~ 	setTextColor(1, 1, 1, 1.0);
--~ 	if self.HUD then
--~ 		if not self.coverEdge.isLoaded then
--~ 			renderText(0.542, 0.918, 0.015, string.format("No Ropes"));
--~ 		end;
--~ 	end;
end;


-- Event


SetHasNetEvent = {};
SetHasNetEvent_mt = Class(SetHasNetEvent, Event);

InitEventClass(SetHasNetEvent, "SetHasNetEvent");

function SetHasNetEvent:emptyNew()
    local self = Event:new(SetHasNetEvent_mt);
    return self;
end;

function SetHasNetEvent:new(vehicle, isLoaded)
    local self = SetHasNetEvent:emptyNew()
    self.vehicle = vehicle;
	self.isLoaded = isLoaded;
    return self;
end;

function SetHasNetEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.vehicle = networkGetObject(id);
	self.isLoaded = streamReadBool(streamId);
    self:run(connection);
end;

function SetHasNetEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteBool(streamId, self.isLoaded);
end;

function SetHasNetEvent:run(connection)
	self.vehicle:setHasNet(self.isLoaded, true);
end;

function SetHasNetEvent.sendEvent(vehicle, isLoaded, noEventSend)
	
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetHasNetEvent:new(vehicle, isLoaded), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetHasNetEvent:new(vehicle, isLoaded));
		end;
	end;
end;



SetHasSpareNetEvent = {};
SetHasSpareNetEvent_mt = Class(SetHasSpareNetEvent, Event);

InitEventClass(SetHasSpareNetEvent, "SetHasSpareNetEvent");

function SetHasSpareNetEvent:emptyNew()
    local self = Event:new(SetHasSpareNetEvent_mt);
    return self;
end;

function SetHasSpareNetEvent:new(vehicle, hasSpare)
    local self = SetHasSpareNetEvent:emptyNew()
    self.vehicle = vehicle;
	self.hasSpare = hasSpare;
    return self;
end;

function SetHasSpareNetEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.vehicle = networkGetObject(id);
	self.hasSpare = streamReadBool(streamId);
    self:run(connection);
end;

function SetHasSpareNetEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteBool(streamId, self.hasSpare);
end;

function SetHasSpareNetEvent:run(connection)
	self.vehicle:setHasSpareNet(self.hasSpare, true);
end;

function SetHasSpareNetEvent.sendEvent(vehicle, hasSpare, noEventSend)
	
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(SetHasSpareNetEvent:new(vehicle, hasSpare), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(SetHasSpareNetEvent:new(vehicle, hasSpare));
		end;
	end;
end;