--
-- 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(savegame)

    self.setWeightPosition = SpecializationUtil.callSpecializationsFunction("setWeightPosition");
    self.setWeight = SpecializationUtil.callSpecializationsFunction("setWeight");
    
    self.numWeightPositions = Utils.getNoNil(getXMLInt(self.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(self.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(self.xmlFile, weightPositionNamei..weightNamei.."#index"));
                    self.weightPosition[i].weight[j].mass = Utils.getNoNil(getXMLInt(self.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;

