--
-- AdditionalWeights
-- Specialization for additional weights on vehicles
--
--	@author:			gotchTOM
--	@date: 				05-Aug-2012
--	@version: 			v0.03 test version!
--
--	@history:			v0.01 - initial implementation
--						v0.02 - emptyMass bugfix???
--						v0.03 - mass bugfix


AdditionalWeights = {};

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

function AdditionalWeights:load(xmlFile)

	self.setWeightPosition = SpecializationUtil.callSpecializationsFunction("setWeightPosition");
	self.setWeight = SpecializationUtil.callSpecializationsFunction("setWeight");
	
	self.numWeightPositions = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.weightPositions#count"), 0);
	if self.numWeightPositions > 0 then	
		self.weightPosition = {};
		for i=1, self.numWeightPositions do
			self.weightPosition[i] = {};
			local weightPositionNamei = string.format("vehicle.weightPositions.weightPosition%d",i);
			self.weightPosition[i].numWeights = Utils.getNoNil(getXMLInt(xmlFile, weightPositionNamei.."#count"), 0);
			if self.weightPosition[i].numWeights > 0 then
				self.weightPosition[i].weight = {};
				self.weightPosition[i].currentWeight = 0;
				self.weightPosition[i].desiredWeight = 0;
				self.weightPosition[i].totalMass = 0;
				self.weightPosition[i].sumCurrentWeightMass = 0;
				for j=1, self.weightPosition[i].numWeights do
					self.weightPosition[i].weight[j] = {};
					local weightNamei = string.format(".weight%d",j)
					self.weightPosition[i].weight[j].weightObject = Utils.indexToObject(self.components, getXMLString(xmlFile, weightPositionNamei..weightNamei.."#index"));
					self.weightPosition[i].weight[j].mass = Utils.getNoNil(getXMLInt(xmlFile, weightPositionNamei..weightNamei.."#mass"));
					setVisibility(self.weightPosition[i].weight[j].weightObject, false);
					self.weightPosition[i].totalMass = self.weightPosition[i].totalMass + self.weightPosition[i].weight[j].mass;
				end;
			end;
		end;
	end;
	
	self.currentWeightPosition = 1;
	self.awCurrentMass = getMass(self.rootNode);
	-- print("load rootNode: "..tostring(self.awCurrentMass));
	self.newMass = self.awCurrentMass;
	self.currentWeightMass = 0;
	
end;

function AdditionalWeights:readStream(streamId, connection)   

	self.currentWeightPosition = streamReadInt8(streamId);
	self.awCurrentMass = streamReadFloat32(streamId);
	-- print("readStream rootNode: "..tostring(self.awCurrentMass));
	setMass(self.rootNode, self.awCurrentMass);
	for i=1, self.numWeightPositions do
		self.weightPosition[i].sumCurrentWeightMass = streamReadInt32(streamId);
		self.weightPosition[i].desiredWeight = streamReadInt32(streamId);
		local desiredWeight = self.weightPosition[i].desiredWeight;
		self.weightPosition[i].currentWeight = desiredWeight
		for j=1, desiredWeight do
			setVisibility(self.weightPosition[i].weight[j].weightObject, true);
		end;	
	end;
end;

function AdditionalWeights:writeStream(streamId, connection)  

	streamWriteInt8(streamId, self.currentWeightPosition);
	streamWriteFloat32(streamId, self.awCurrentMass);	
	for i=1, self.numWeightPositions do
		streamWriteInt32(streamId, self.weightPosition[i].sumCurrentWeightMass);
		streamWriteInt32(streamId, self.weightPosition[i].desiredWeight);
	end;
end;

function AdditionalWeights:delete()
end;

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

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

function AdditionalWeights:update(dt)
		
	if self:getIsActive() then
		if self:getIsActiveForInput() then
			if self.numWeightPositions > 0 then	
				if self.numWeightPositions > 1 then
					if InputBinding.hasEvent(InputBinding.TOGGLE_ADDWEIGHT) and Input.isKeyPressed(Input.KEY_lalt) then
						self:setWeightPosition(false);
					end;
				end;
				if self.weightPosition[self.currentWeightPosition].numWeights > 0 then
					if InputBinding.hasEvent(InputBinding.TOGGLE_ADDWEIGHT) and not Input.isKeyPressed(Input.KEY_lalt) then
						self:setWeight(false);
					end;
				end;	
			end;	
		end;
	end;	
end;

function AdditionalWeights:updateTick(dt)
	
	if self.awCurrentMass == 0 then
		self.awCurrentMass = getMass(self.rootNode);
		-- print("updateTick rootNode: "..tostring(self.awCurrentMass));
		self.newMass = self.awCurrentMass;
	end;
	if self:getIsActive() then
		local currentWeight = self.weightPosition[self.currentWeightPosition].currentWeight;
		local desiredWeight = self.weightPosition[self.currentWeightPosition].desiredWeight;
		local numWeights = self.weightPosition[self.currentWeightPosition].numWeights;
		if desiredWeight > numWeights then
			desiredWeight = 0;
			self.weightPosition[self.currentWeightPosition].desiredWeight = desiredWeight;
		end;
		if currentWeight ~= desiredWeight then
			self.weightPosition[self.currentWeightPosition].currentWeight = self.weightPosition[self.currentWeightPosition].currentWeight + 1;
			currentWeight = self.weightPosition[self.currentWeightPosition].currentWeight;
			if currentWeight > numWeights then
				currentWeight = 0;
				self.weightPosition[self.currentWeightPosition].currentWeight = currentWeight;
				for i=1, numWeights do
					setVisibility(self.weightPosition[self.currentWeightPosition].weight[i].weightObject, false);
				end;
				self.currentWeightMass = 0;
				self.weightPosition[self.currentWeightPosition].sumCurrentWeightMass = 0;
				self.newMass = self.awCurrentMass - self.weightPosition[self.currentWeightPosition].totalMass/1000;
			elseif currentWeight > 0 then
				setVisibility(self.weightPosition[self.currentWeightPosition].weight[currentWeight].weightObject, true);
				self.currentWeightMass = self.weightPosition[self.currentWeightPosition].weight[currentWeight].mass;
				self.newMass = self.awCurrentMass + self.currentWeightMass/1000;
				self.weightPosition[self.currentWeightPosition].sumCurrentWeightMass = self.weightPosition[self.currentWeightPosition].sumCurrentWeightMass + self.currentWeightMass;
			end;
			if self.newMass ~= self.awCurrentMass then
				setMass(self.rootNode, self.newMass);
				self.awCurrentMass = self.newMass;
				for k,v in pairs(self.components) do
					if v.node == self.rootNode then
						if v.centerOfMass ~= nil then
							setCenterOfMass(v.node, v.centerOfMass[1], v.centerOfMass[2], v.centerOfMass[3]);
						end;
						break;
					end;
				end;
			end;
		end;	
	end;	
	
end;

function AdditionalWeights:draw()
	
	if self.numWeightPositions > 0 then
		
		g_currentMission:addHelpButtonText(g_i18n:getText("TOGGLE_ADDWEIGHT"),InputBinding.TOGGLE_ADDWEIGHT);
		
		if self.numWeightPositions == 1 then
			g_currentMission:addExtraPrintText(g_i18n:getText("extraWeightsTxt2")..string.format(" %s",self.weightPosition[self.currentWeightPosition].sumCurrentWeightMass).."kg "..g_i18n:getText("extraWeightsTxt1")..string.format(" %s",self.weightPosition[self.currentWeightPosition].totalMass).."kg  ("..string.format("%.3f",self.awCurrentMass).."t)")
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("TOGGLE_ADDWEIGHTPOS"),InputBinding.TOGGLE_ADDWEIGHT);
			g_currentMission:addExtraPrintText(g_i18n:getText("extraWeightsTxt3")..string.format(" %s",self.currentWeightPosition)..string.format(" -> %s",self.weightPosition[self.currentWeightPosition].sumCurrentWeightMass).."kg "..g_i18n:getText("extraWeightsTxt1")..string.format(" %s",self.weightPosition[self.currentWeightPosition].totalMass).."kg  ("..string.format("%.3f",self.awCurrentMass).."t)")
		end;
	end;
	
end;

function AdditionalWeights:setWeight(noEventSend)

	if noEventSend == nil or noEventSend == false then	
		SetWeightEvent.sendEvent(self, noEventSend); 	
	end;
	self.weightPosition[self.currentWeightPosition].desiredWeight = self.weightPosition[self.currentWeightPosition].desiredWeight + 1;
end;

function AdditionalWeights:setWeightPosition(noEventSend)

	if noEventSend == nil or noEventSend == false then	
		SetWeightPositionEvent.sendEvent(self, noEventSend); 	
	end;
	self.currentWeightPosition = self.currentWeightPosition + 1;
	if self.currentWeightPosition > self.numWeightPositions then
		self.currentWeightPosition = 1;
	end;
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)

    local self = SetWeightEvent:emptyNew()
    self.vehicle = vehicle;
    return self;
end;

function SetWeightEvent:readStream(streamId, connection) 

    local id = streamReadInt32(streamId);  
    self.vehicle = networkGetObject(id); 
    self:run(connection);
end;

function SetWeightEvent:writeStream(streamId, connection) 
  
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
end;

function SetWeightEvent:run(connection) 
  
	if not connection:getIsServer() then	
		for k, v in pairs(g_server.clientConnections) do
			if v ~= connection and not v:getIsLocal() then
				v:sendEvent(SetWeightEvent:new(self.vehicle));
			end;
		end;
	end;	
	self.vehicle:setWeight(true); 
end;

function SetWeightEvent.sendEvent(vehicle, currentWeight, noEventSend)  
		
	if g_server ~= nil then  
		g_server:broadcastEvent(SetWeightEvent:new(vehicle), nil, nil, vehicle);
	else  
		g_client:getServerConnection():sendEvent(SetWeightEvent:new(vehicle));
	end;
end;






SetWeightPositionEvent = {};
SetWeightPositionEvent_mt = Class(SetWeightPositionEvent, Event);

InitEventClass(SetWeightPositionEvent, "SetWeightPositionEvent");

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

function SetWeightPositionEvent:new(vehicle)

    local self = SetWeightPositionEvent:emptyNew()
    self.vehicle = vehicle;
    return self;
end;

function SetWeightPositionEvent:readStream(streamId, connection) 

    local id = streamReadInt32(streamId);  
    self.vehicle = networkGetObject(id); 
    self:run(connection);
end;

function SetWeightPositionEvent:writeStream(streamId, connection) 
  
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
end;

function SetWeightPositionEvent:run(connection) 
  
	if not connection:getIsServer() then	
		for k, v in pairs(g_server.clientConnections) do
			if v ~= connection and not v:getIsLocal() then
				v:sendEvent(SetWeightPositionEvent:new(self.vehicle));
			end;
		end;
	end;	
	self.vehicle:setWeightPosition(true); 
end;

function SetWeightPositionEvent.sendEvent(vehicle, currentWeight, noEventSend)  
		
	if g_server ~= nil then  
		g_server:broadcastEvent(SetWeightPositionEvent:new(vehicle), nil, nil, vehicle);
	else  
		g_client:getServerConnection():sendEvent(SetWeightPositionEvent:new(vehicle));
	end;
end;

