--
-- extraWeights
--
-- Inspired by PeterJ (fs-uk mod team) front_weight script
-- @author:    	Xentro (www.fs-uk.com)(Marcus@Xentro.se)
-- @version:    v1.01
-- @date:       2013-08-04
-- 
--[[
<extraWeights playerInteractionIndex="" massScale="50" massComponent="1">
	<weight index="" />
</extraWeights>
]]--

extraWeights = {};

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

function extraWeights:load(xmlFile)
  	self.setWeight = SpecializationUtil.callSpecializationsFunction("setWeight");
	self.playerInWeightRange = extraWeights.playerInWeightRange;
	
	local input = getXMLString(xmlFile, "vehicle.extraWeights#inputBinding");
	if input ~= nil and InputBinding[input] ~= nil then
		self.ew_input = InputBinding[input];
	else
		self.ew_input = InputBinding.IMPLEMENT_EXTRA3;
	end;
	
	local playerInteractionNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.extraWeights#playerInteractionIndex"));
	
	if playerInteractionNode ~= nil then
		local massComponent = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.extraWeights#massComponent"), 1)
		
		if massComponent ~= nil and self.components[massComponent] ~= nil then
			local entry = {};
			entry.weights = {};
			
			local w = 0;
			while true do
				local keyFor = string.format("vehicle.extraWeights.weight(%d)", w);
				if not hasXMLProperty(xmlFile, keyFor) then break; end;
				
				local node = Utils.indexToObject(self.components, getXMLString(xmlFile, keyFor .. "#index"));
				if node ~= nil then
					setVisibility(node, false);
					table.insert(entry.weights, node);
				else
					print("Warning: weight index was nil in " .. self.configFileName);
				end;
				
				w = w + 1;
			end;
			
			if table.getn(entry.weights) > 0 then
				entry.playerInteractionNode = playerInteractionNode;
				entry.massComponent = massComponent;
				entry.currentLevel = 0;
				entry.currentWeight = 0;
				entry.numMax = w;
				entry.allowInput = true;
				entry.startMass = getMass(self.components[massComponent].node);
				entry.massScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraWeights#massScale"), 100);
				entry.massScaleDivider = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraWeights#massScaleDivider"), 1000);
				entry.debug = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.extraWeights#debug"), false);
				
				self.extraWeights = entry;
			else
				print("Warning: there are no weights in " .. self.configFileName);
			end;
		else
			print("Error: component (".. massComponent ..") can't be found in " .. self.configFileName);
		end;
	else
		print("Error: playerInteractionIndex was nil in " .. self.configFileName);
	end;
	
	local startId = getXMLInt(xmlFile, "vehicle.extraWeights#startId");
	
	if startId ~= nil then
		self:setWeight(startId, true);
	end;
end;

function extraWeights:delete()
end;

function extraWeights:readStream(streamId, connection)
	if self.extraWeights ~= nil then
		self:setWeight(streamReadInt8(streamId), true);
	end;
end;

function extraWeights:writeStream(streamId, connection)
	if self.extraWeights ~= nil then
		streamWriteInt8(streamId, self.extraWeights.currentLevel);
	end;
end;

function extraWeights:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local currentLevel = getXMLInt(xmlFile, key .. "#currentLevel");
	
	if currentLevel ~= nil then
		self:setWeight(currentLevel, true);
	end;
	
	return BaseMission.VEHICLE_LOAD_OK;
end;

function extraWeights:getSaveAttributesAndNodes(nodeIdent)
	local attributes;
	
	if self.extraWeights ~= nil then
		attributes = 'currentLevel="' .. self.extraWeights.currentLevel .. '"';
	end;
	
	return attributes, nil;
end;

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

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

function extraWeights:update(dt)
	if self.extraWeights ~= nil then
		if self.extraWeights.startMass == nil or self.extraWeights.startMass == 0 then
			self.extraWeights.startMass = getMass(self.components[self.extraWeights.massComponent].node);
		end;
		
		if g_currentMission.player ~= nil and self.extraWeights.allowInput then
			local ew = self.extraWeights;
			
			if self:playerInWeightRange(ew.playerInteractionNode, g_currentMission.player) then
				if g_i18n:hasText("ADD_WEIGHT") then
					g_currentMission:addHelpButtonText(g_i18n:getText("ADD_WEIGHT"), self.ew_input);
				end;
				if g_i18n:hasText("CURRENT_WEIGHT") then
					g_currentMission:addExtraPrintText(string.format(g_i18n:getText("CURRENT_WEIGHT"), ew.currentWeight));
				end;
				
				if InputBinding.hasEvent(self.ew_input) and g_gui.currentGui == nil and not g_currentMission.isPlayerFrozen then
					self:setWeight(math.abs(ew.currentLevel + 1));
				end;
			end;
		end;
	end;
end;

function extraWeights:updateTick(dt)
	if self.extraWeights ~= nil then
		local ew = self.extraWeights;
		local newMass = ew.startMass + (ew.currentWeight / ew.massScaleDivider); 
		
		if newMass <= 0 then
			newMass = 0.001;
		end;
		
		if newMass ~= ew.currentMass then
			setMass(self.components[ew.massComponent].node, newMass);
			ew.currentMass = newMass;
			if ew.debug then
				print("level " .. ew.currentLevel .. " massScale " .. ((ew.currentLevel * ew.massScale) / ew.massScaleDivider) .. " newMass " .. (newMass - ew.startMass) .. " totalMass " .. newMass);
			end;
		end;
	end;
end;

function extraWeights:draw()
end;

function extraWeights:setWeight(level, noEventSend)
	if level > self.extraWeights.numMax or level < 0 then
		level = 0;
	end;
	
	self.extraWeights.currentLevel = level;
	self.extraWeights.currentWeight = level * self.extraWeights.massScale;
	
	for k, node in pairs(self.extraWeights.weights) do
		if k <= level then
			setVisibility(node, true);
		else
			setVisibility(node, false);
		end;		
	end;
	
	setWeightEvent.sendEvent(self, level, noEventSend);
end;

function extraWeights:playerInWeightRange(location, player)
	local x, y, z = getWorldTranslation(location);
	local px, py, pz = getWorldTranslation(player.rootNode);
	local distance = Utils.vector3Length(x - px, y - py, z - pz);
	if distance < 1.5 then
		return true;
	end;
	
	return false;
end;

setWeightEvent = {};
setWeightEvent_mt = Class(setWeightEvent, Event);

InitEventClass(setWeightEvent, "setWeightEvent");

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

function setWeightEvent:new(vehicle, weightLevel)
    local self = setWeightEvent:emptyNew()
    self.vehicle = vehicle;
	self.weightLevel = weightLevel;
    return self;
end;

function setWeightEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
	self.weightLevel = streamReadInt8(streamId);
    self:run(connection);
end;

function setWeightEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.weightLevel);	
end;

function setWeightEvent:run(connection)
	self.vehicle:setWeight(self.weightLevel, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(setWeightEvent:new(self.vehicle, self.weightLevel), nil, connection, self.vehicle);
	end;
end;

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