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

Cabsuspension = {};

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

function Cabsuspension:load(savegame)
    -- Cabsuspension animation
    self.maxTranslationPrCycleCabin     = 0.00008;
    self.maxTranslationPrCycleCabin2     = 0.00004;
    self.cab = {};
    self.cab.rotNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.cab#rotNode"));

    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.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(self.xmlFile, "vehicle.wheels.wheel(0)#suspTravel")/2; -- /2 or /3 or ??
        self.fr_t = getXMLFloat(self.xmlFile, "vehicle.wheels.wheel(1)#suspTravel")/2;
        self.bl_t = getXMLFloat(self.xmlFile, "vehicle.wheels.wheel(2)#suspTravel")/2;
        self.br_t = getXMLFloat(self.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;
    
    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.maxSeatTranslationPrCycle = 0.00008;
    self.seatTranslation = 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)

    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);

            
            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));
            

            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
                                
                -- 1.                
                local t = -w[2]*Utils.degToRad(6);
                if self.cabXRot > t + self.maxTranslationPrCycleCabin2 * 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;
                end;        
                -- 2.
                if self.cabXRot < t - self.maxTranslationPrCycleCabin2 * 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;
                end;
                --self.cabXRot = -w[2]*Utils.degToRad(6);

                -- 1.
                local t = -w[1]*Utils.degToRad(6);
                if self.cabZrot > t + self.maxTranslationPrCycleCabin2 * 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 * 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;
        
                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 + 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);
            
        end;
        
        
    
    end;
    
end;

function Cabsuspension:updateTick(dt)

end;

function Cabsuspension:draw()
end;

function Cabsuspension:onLeave()

end;

function Cabsuspension:onEnter()

end;
