--
-- Cabsuspension
-- Specialization for Cabsuspension
--
-- @author  JoXXer
-- @date  17/09/11
-- @version 1.0 - JoXXer
--            2.0    - rework by fruktor
--                - Additional edits by Spartan086


Cabsuspension = {};

function Cabsuspension.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function Cabsuspension:load(savegame)
    -- Cabsuspension animation
    self.maxSeatTranslationPrCycle = 0.00004;
    self.maxTranslationPrCycleCabin     = 0.00004;
    self.maxTranslationPrCycleCabin2     = 0.00002;
    self.cab = {};
    self.cab.limitRot = 2.5;
    
    self.cab.rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cab#rotNode"));
    self.cab.enabledNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cab#enabledNode"));
    self.cab.enabled = true;

    if self.cab.rotNode~=nil then
        local x,y,z = getTranslation(self.cab.rotNode);
        self.startCabXTranslation = x;
        self.startCabYTranslation = y;
        self.startCabZTranslation = z;

        local xRot,yRot,zRot = getRotation(self.cab.rotNode);
        self.cabXRot = xRot;
        self.cabYrot = yRot;
        self.cabZrot = zRot;
    end;    

    if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil and self.wheels[1].repr ~= nil and self.wheels[2].repr ~= nil then
        local x1,y1,z1 = getTranslation(self.wheels[1].repr);    -- FRONT left
        local x2,y2,z2 = getTranslation(self.wheels[2].repr);    -- FRONT right
        local x3,y3,z3 = getTranslation(self.wheels[3].repr);    -- BACK left
        local x4,y4,z4 = getTranslation(self.wheels[4].repr);    -- BACK right
        
        -- ! manual offsets after measurement, see deubg string in update
        self.fl = y1 - 0.00;
        self.fr = y2 - 0.00;
        self.bl = y3 - 0.00;
        self.br = y4 - 0.00;
        
        self.fl_d = 0;
        self.fr_d = 0;
        self.bl_d = 0;
        self.br_d = 0;
        
        self.fl_m = 0;
        self.fr_m = 0;
        self.bl_m = 0;
        self.br_m = 0;
        
        self.fl_cur = 0;
        self.fr_cur = 0;
        self.bl_cur = 0;
        self.br_cur = 0;        

        self.fl_last = 0;
        self.fr_last = 0;
        self.bl_last = 0;
        self.br_last = 0;        

        self.fl_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(0)#suspTravel")/2; -- /2 or /3 or ??
        self.fr_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(1)#suspTravel")/2;
        self.bl_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(2)#suspTravel")/2;
        self.br_t = getXMLFloat(xmlFile, "vehicle.wheels.wheel(3)#suspTravel")/2;
        self.normVal = math.max( math.abs(self.fl_t), math.max( math.abs(self.fr_t), 
            math.max( math.abs(self.bl_t), math.max( math.abs(self.br_t) ) ) ) );
    end;

    self.cabTranslation = self.averageYTranslationCab;
    self.cabTranslationStart = self.cabTranslation;
    
    
    -- Seat animation
    self.seatNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.seatNode#index"));
    self.kameraNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.kamera#index"));
    self.seatSuspensionNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.seatNode#seatBase"));
    
    
    if self.seatNode ~=nil then
        local x,y,z = getTranslation(self.seatNode);
        self.startSeatXTranslation = x;
        self.startSeatYTranslation = y;
        self.startSeatZTranslation = z;
    end;

    if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
        local x,y,z = getTranslation(self.wheels[3].repr);
        local x2,y2,z2 = getTranslation(self.wheels[4].repr);
        local x3,y3,z3 = getTranslation(self.wheels[1].repr);
        local x3,y4,z4 = getTranslation(self.wheels[2].repr);
        self.averageYTranslation = (y + y2 + y3 + y4)/4;
    end;

    self.seatTranslation = self.startSeatYTranslation; --self.averageYTranslation;
    self.defaultPosition = self.averageYTranslation;    

    self.time2 = 0;
end;

function Cabsuspension:delete()
end;

function Cabsuspension:readStream(streamId, connection)
end;

function Cabsuspension:writeStream(streamId, connection)
end;

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

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

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

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

function Cabsuspension:update(dt)
    if self.cab.enabledNode ~= nil then
        self.cab.enabled = getVisibility(self.cab.enabledNode);
    end;
    if InputBinding.hasEvent(InputBinding.TXCABSUSP) then
        --print("disable!");        
        setTranslation(self.seatNode, self.startSeatXTranslation, self.startSeatYTranslation, self.startSeatZTranslation);
        setRotation(self.seatNode, 0, 0, 0);
        setRotation(self.cab.rotNode, 0, 0, 0);
        self.cab.enabled = not self.cab.enabled;
    end;
    
    if self:getIsActiveForInput() and self.isEntered then
        if self.cab.enabled then
            g_currentMission:addHelpButtonText(g_i18n:getText("TXCABSUSPOFF"), InputBinding.TXCABSUSP);
        else
            g_currentMission:addHelpButtonText(g_i18n:getText("TXCABSUSPON"), InputBinding.TXCABSUSP);
        end;
    end;
    
    if self.cab.enabled == false then
        return;
    end;

    --if self.cab.dummyNode ~= nil and getVisibility(self.cab.dummyNode) ~= true then
        --print("Cab suspension disabled");
        --return;
    --end;


    if self.lastSpeed > -0.0005 and self.lastSpeed < 0.0005 then
        return;
    end;

    self.time2 = self.time2 + dt;

    -- Cabsuspension animation
    if self.isClient then
        if self.cab.rotNode ~= nil and self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
        
            local x1,y1,z1 = getTranslation(self.wheels[1].repr);
            local x2,y2,z2 = getTranslation(self.wheels[2].repr);
            local x3,y3,z3 = getTranslation(self.wheels[3].repr);
            local x4,y4,z4 = getTranslation(self.wheels[4].repr);
            
            --print("y1/2/3/4 = "..y1.." / "..y2.." / "..y3.." / "..y4);
            
            --self.fl_d = self.fl - y1;
            --self.fr_d = self.fr - y2;
            --self.bl_d = self.bl - y3;
            --self.br_d = self.br - y4;
            
            self.fl_cur = y1 - self.fl;
            self.fr_cur = y2 - self.fr;
            self.bl_cur = y3 - self.bl;
            self.br_cur = y4 - self.br;

            --self.fl_d = self.fl_cur;
            
            self.fl_d = 0.1*self.fl_d + 0.9*(self.fl_cur - self.fl_last); --
            self.fr_d = 0.1*self.fr_d + 0.9*(self.fr_cur - self.fr_last); --
            self.bl_d = 0.1*self.bl_d + 0.9*(self.bl_cur - self.bl_last); --0.1
            self.br_d = 0.1*self.br_d + 0.9*(self.br_cur - self.br_last); --0.1
            
            self.fl_d = (self.fl_cur - self.fl_last); 
            self.fr_d = (self.fr_cur - self.fr_last); 
            self.bl_d = (self.bl_cur - self.bl_last); 
            self.br_d = (self.br_cur - self.br_last); 
            
            local max_d = self.fl_d/self.fl_t;
            if math.abs(self.fr_d/self.fr_t) > math.abs(max_d) then
                max_d = self.fr_d/self.fr_t;
            end;
            if math.abs(self.bl_d/self.bl_t) > math.abs(max_d) then
                max_d = self.bl_d/self.bl_t;
            end;
            if math.abs(self.br_d/self.br_t) > math.abs(max_d) then
                max_d = self.br_d/self.br_t;
            end;

            self.fl_last = self.fl_cur;
            self.fr_last = self.fr_cur;
            self.bl_last = self.bl_cur;
            self.br_last = self.br_cur;

            -- 1.
            if self.fl_m > self.fl_d then
                self.fl_m = self.fl_m - self.maxTranslationPrCycleCabin * dt;
                if self.fl_m < self.fl_d then
                    self.fl_m = self.fl_d;
                end;
            end;
            if self.fr_m > self.fr_d then
                self.fr_m = self.fr_m - self.maxTranslationPrCycleCabin * dt;
                if self.fr_m < self.fr_d then
                    self.fr_m = self.fr_d;
                end;
            end;        
            if self.bl_m > self.bl_d then
                self.bl_m = self.bl_m - self.maxTranslationPrCycleCabin * dt;
                if self.bl_m < self.bl_d then
                    self.bl_m = self.bl_d;
                end;
            end;        
            if self.br_m > self.br_d then
                self.br_m = self.br_m - self.maxTranslationPrCycleCabin * dt;
                if self.br_m < self.br_d then
                    self.br_m = self.br_d;
                end;
            end;        
            
            -- 2.
            if self.fl_m < self.fl_d then
                self.fl_m = self.fl_m + self.maxTranslationPrCycleCabin * dt;
                if self.fl_m > self.fl_d then
                    self.fl_m = self.fl_d;
                end;
            end;
            if self.fr_m < self.fr_d then
                self.fr_m = self.fr_m + self.maxTranslationPrCycleCabin * dt;
                if self.fr_m > self.fr_d then
                    self.fr_m = self.fr_d;
                end;
            end;        
            if self.bl_m < self.bl_d then
                self.bl_m = self.bl_m + self.maxTranslationPrCycleCabin * dt;
                if self.bl_m > self.bl_d then
                    self.bl_m = self.bl_d;
                end;
            end;        
            if self.br_m < self.br_d then
                self.br_m = self.br_m + self.maxTranslationPrCycleCabin * dt;
                if self.br_m > self.br_d then
                    self.br_m = self.br_d;
                end;
            end;        

            --
            local w = {0,0};
            local maxVal = 1;
            
            w[1] = w[1] +  1*math.max(-maxVal,math.min(maxVal,self.fl_d/self.fl_t));
            w[2] = w[2] +  1*math.max(-maxVal,math.min(maxVal,self.fl_d/self.fl_t));
        
            w[1] = w[1] + -1*math.max(-maxVal,math.min(maxVal,self.fr_d/self.fr_t));
            w[2] = w[2] +  1*math.max(-maxVal,math.min(maxVal,self.fr_d/self.fr_t));
            
            w[1] = w[1] +  1*math.max(-maxVal,math.min(maxVal,self.bl_d/self.bl_t));
            w[2] = w[2] + -1*math.max(-maxVal,math.min(maxVal,self.bl_d/self.bl_t));

            w[1] = w[1] + -1*math.max(-maxVal,math.min(maxVal,self.br_d/self.br_t));
            w[2] = w[2] + -1*math.max(-maxVal,math.min(maxVal,self.br_d/self.br_t));
            
            -- print a debug string to see offsets
            --local dstr = string.format("%6.3f %6.3f --- %6.3f %6.3f --- %6.3f %6.3f --- %6.3f %6.3f --- :: %6.3f %6.3f ", 
            --    self.fl_d, self.fl_m, self.fr_d, self.fr_m, self.bl_d, self.bl_m, self.br_d, self.br_m, w[1], w[2] );
            --local dstr = string.format("%6.3f %6.3f %6.3f %6.3f", self.fl_d/self.fl_t, self.fr_d/self.fr_t, self.bl_d/self.bl_t, self.br_d/self.br_t );
            --print(dstr); 
            
            --dstr = string.format("  :::::  %6.3f %6.3f ", w[1], w[2] );
            --print(self.time.." "..self.time2.."   "..dstr); 


            -- 

            w[1] = math.max(math.min(1,w[1]),-1);
            w[2] = math.max(math.min(1,w[2]),-1);
                
            if self.cab.rotNode ~= nil then
                --setTranslation(self.cab.rotNode, self.startCabXTranslation, self.cabTranslation + self.wheelYTranslationDifference, self.startCabZTranslation);
                --setTranslation(self.cab.rotNode, self.startCabXTranslation, self.startCabYTranslation + cabdiff, self.startCabZTranslation);
                
                -- 1.                
                local t = -w[2]*Utils.degToRad(6);
                if self.cabXRot > t + self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
                    self.cabXRot = self.cabXRot - self.maxTranslationPrCycleCabin2*dt; --math.max(0.01, math.abs(w[2])) * dt;
                    --if self.cabXRot < t then
                        --self.cabXRot = t;
                    --end;
                -- 2.
                elseif self.cabXRot < t - self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
                    self.cabXRot = self.cabXRot + self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[2])) * dt;
                    --if self.cabXRot > t then
                        --self.cabXRot = t;
                    --end;
                --else
                    --self.cabXRot = 0;
                end;
                --self.cabXRot = -w[2]*Utils.degToRad(6);

                -- 1.
                local t = -w[1]*Utils.degToRad(6);
                if self.cabZrot > t + self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
                    self.cabZrot = self.cabZrot - self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[1])) * dt;
                    --if self.cabZrot < t then
                        --self.cabZrot = t;
                    --end;
                end;        
                -- 2.
                if self.cabZrot < t - self.maxTranslationPrCycleCabin2 * self.cab.limitRot * dt then
                    self.cabZrot = self.cabZrot + self.maxTranslationPrCycleCabin2*dt; --*math.max(0.01, math.abs(w[1])) * dt;
                    --if self.cabZrot > t then
                        --self.cabZrot = t;
                    --end;
                end;
                --self.cabZrot = -w[1]*Utils.degToRad(6);            
                
                --self.cabXRot = self.xrot; --math.max( Utils.degToRad(-5), math.min( Utils.degToRad(5), self.cabXRot ) );
                --self.cabZrot = self.zrot; --w[1]*Utils.degToRad(8); --math.max( Utils.degToRad(-3), math.min( Utils.degToRad(3), self.cabZrot ) );
                setRotation(self.cab.rotNode, self.cabXRot, 0, self.cabZrot);
                
                --print("self.cabXRot="..tostring(math.deg(self.cabXRot)).."   self.cabZrot="..tostring(math.deg(self.cabZrot)));
            end;
            
            --max_d
            
            --local t = self.startSeatYTranslation + w[2]*0.25; TOTO BOLO ORIGINAL
            local t = self.startSeatYTranslation + w[2]*5;
            
            --local t = self.startSeatYTranslation + max_d*0.25;
            
            if self.seatTranslation > t then -- + self.maxSeatTranslationPrCycle * dt then
                self.seatTranslation = self.seatTranslation - self.maxSeatTranslationPrCycle * dt;
                if self.seatTranslation < t then
                    self.seatTranslation = t;
                end;
            elseif self.seatTranslation < t then -- - self.maxSeatTranslationPrCycle * dt then
                self.seatTranslation = self.seatTranslation + self.maxSeatTranslationPrCycle * dt;
                if self.seatTranslation > t then
                    self.seatTranslation = t;
                end;
            end;            
            setTranslation(self.seatNode, self.startSeatXTranslation, self.seatTranslation, self.startSeatZTranslation);
            setRotation(self.seatNode, self.cabXRot*(-1), 0, self.cabZrot*(-1));
            
            --setRotation(self.kameraNode, self.cabXRot*(-3), 0, self.cabZrot*(-5));            
            
            
        end;
        
        
        -- Seat animation
        --[[
        if self.wheels[3].repr ~= nil and self.wheels[4].repr ~= nil then
            local x,y,z = getTranslation(self.wheels[3].repr);
            local x2,y2,z2 = getTranslation(self.wheels[4].repr);
            local x3,y3,z3 = getTranslation(self.wheels[1].repr);
            local x3,y4,z4 = getTranslation(self.wheels[2].repr);
            self.averageYTranslation = (y + y2 + y3 + y4)/4;
        end;

        if self.seatTranslation > self.averageYTranslation + self.maxSeatTranslationPrCycle * dt then
            self.seatTranslation = self.seatTranslation - self.maxSeatTranslationPrCycle * dt;
            if self.seatTranslation < self.averageYTranslation then
                self.seatTranslation = self.averageYTranslation;
            end;
        elseif self.seatTranslation < self.averageYTranslation - self.maxSeatTranslationPrCycle * dt then
            self.seatTranslation = self.seatTranslation + self.maxSeatTranslationPrCycle * dt;
            if self.seatTranslation > self.averageYTranslation then
                self.seatTranslation = self.averageYTranslation;
            end;
        end;

        local transDiff = 0;
        local defaultHeight = 0.255;
        local newHeight = 0;

        transDiff = self.seatTranslation - self.defaultPosition;
        newHeight = defaultHeight + transDiff;
        local newScale = newHeight / defaultHeight;

        if self.seatNode ~= nil and self.seatSuspensionNode ~= nil then
            setTranslation(self.seatNode, self.startSeatXTranslation, self.seatTranslation + 0.1, self.startSeatZTranslation);
            --setScale(self.seatSuspensionNode, 1, 1, newScale);
        end;
        ]]--
        
    end;
    
end;

function Cabsuspension:updateTick(dt)

end;

function Cabsuspension:draw()
end;

function Cabsuspension:onLeave()

end;

function Cabsuspension:onEnter()

end;
