--
-- PaukAxis
-- This is the specialization for vehicles which steer with an articulated axis (excavators, loaders ...)
--
-- @author  Stefan Geiger
-- @date  18/08/09
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.

PaukAxis = {};

function PaukAxis.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Drivable, specializations);
end;

function PaukAxis:load(savegame)
    PaukAxis.loadPaukAxis(self, self.xmlFile);
end;

function PaukAxis:loadPaukAxis(xmlFile, isInitialized)
    --- increase rpm ---
     self.setVehicleRpmUp = SpecializationUtil.callSpecializationsFunction("setVehicleRpmUp");
    self.saveMinRpm = self.motor.minRpm;
    
    local index = getXMLInt(xmlFile, "vehicle.paukAxis#componentJointIndex");
    if index ~= nil then
        local componentJoint = self.componentJoints[index+1];
        local rotSpeed = getXMLFloat(xmlFile, "vehicle.paukAxis#rotSpeed");
        local rotMax = getXMLFloat(xmlFile, "vehicle.paukAxis#rotMax");
        local rotMin = getXMLFloat(xmlFile, "vehicle.paukAxis#rotMin");
        if componentJoint ~= nil and rotSpeed ~= nil and rotMax ~= nil and rotMin ~= nil then
            rotSpeed = math.rad(rotSpeed);
            rotMax = math.rad(rotMax);
            rotMin = math.rad(rotMin);
            local entry = {};

            entry.componentJoint = componentJoint;
            entry.anchorActor = Utils.getNoNil(getXMLInt(xmlFile,  "vehicle.paukAxis#anchorActor"), 0);
            if not isInitialized then
                entry.rotNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.paukAxis#rotNode"));
            end;
            entry.rotMax = rotMax;
            entry.rotMin = rotMin;
            entry.rotSpeed = rotSpeed;

            local maxRotTime = rotMax/rotSpeed;
            local minRotTime = rotMin/rotSpeed;
            if minRotTime > maxRotTime then
                local temp = minRotTime;
                minRotTime = maxRotTime;
                maxRotTime = temp;
            end;
            if maxRotTime > self.maxRotTime then
                self.maxRotTime = maxRotTime;
            end;
            if minRotTime < self.minRotTime then
                self.minRotTime = minRotTime;
            end;

            entry.curRot = 0;

            local i = 0;
            entry.rotatingParts = {};
            while true do
                local node = Utils.indexToObject(self.components, getXMLString(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#index", i)));
                if node == nil then
                    break;
                end;
                local rotatingPart = {};
                rotatingPart.node = node;
                local rx, ry, rz = getRotation(node);
                rotatingPart.defRot = {rx, ry, rz};
                rotatingPart.posRot = Utils.getRadiansFromString(getXMLString(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#posRot", i)), 3);
                rotatingPart.negRot = Utils.getRadiansFromString(getXMLString(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#negRot", i)), 3);
                rotatingPart.negRotFactor = Utils.getNoNil(getXMLFloat(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#negRotFactor", i)), 1);
                rotatingPart.posRotFactor = Utils.getNoNil(getXMLFloat(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#posRotFactor", i)), 1);
                rotatingPart.invertSteeringAngle = Utils.getNoNil(getXMLBool(xmlFile, string.format("vehicle.paukAxis.rotatingPart(%d)#invertSteeringAngle", i)), false);
                table.insert(entry.rotatingParts, rotatingPart);
                i = i + 1;
            end;

            self.paukAxis = entry;
        end;
    end;

    self.interpolatedRotatedTime = 0;
end;

function PaukAxis:delete()
end;

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

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

function PaukAxis:update(dt)
    if self:getIsActive() then
        local revUp = false;
        if self.paukAxis ~= nil then

            local curRot = self.paukAxis.curRot;
            if self.interpolatedRotatedTime < self.rotatedTime then
                self.interpolatedRotatedTime = math.min(self.rotatedTime, self.interpolatedRotatedTime + math.abs(self.paukAxis.rotSpeed) * dt/500);
            elseif self.interpolatedRotatedTime > self.rotatedTime then
                self.interpolatedRotatedTime = math.max(self.rotatedTime, self.interpolatedRotatedTime - math.abs(self.paukAxis.rotSpeed) * dt/500);
            end;

            local steeringAngle = self.interpolatedRotatedTime * self.paukAxis.rotSpeed;
            if steeringAngle > self.paukAxis.rotMax then
                steeringAngle = self.paukAxis.rotMax;
            elseif steeringAngle < self.paukAxis.rotMin then
                steeringAngle = self.paukAxis.rotMin;
            end;
            if self.updatePaukAxisRotation ~= nil then
                steeringAngle = self:updatePaukAxisRotation(steeringAngle, dt);
            end;
            if math.abs(steeringAngle - curRot) > 0.000001 then
                if self.isServer then
                    local rotNode = Utils.getNoNil(self.paukAxis.rotNode, self.paukAxis.componentJoint.jointNode);
                    setRotation(rotNode, 0, steeringAngle, 0);
                    setJointFrame(self.paukAxis.componentJoint.jointIndex, self.paukAxis.anchorActor, self.paukAxis.componentJoint.jointNode);
                    self.paukAxis.curRot = steeringAngle;
                end;

                if self.isClient then
                    local percent = 0;
                    if steeringAngle > 0 then
                        percent = steeringAngle / self.paukAxis.rotMax;
                        revUp = true;
                    elseif steeringAngle < 0 then
                        revUp = true;
                        percent = steeringAngle / self.paukAxis.rotMin;
                    end;
                    for i,rotPart in pairs(self.paukAxis.rotatingParts) do
                        local rx,ry,rz;
                        if (steeringAngle > 0 and not rotPart.invertSteeringAngle) or (steeringAngle < 0 and rotPart.invertSteeringAngle) then
                            rx,ry,rz = Utils.vector3ArrayLerp(rotPart.defRot, rotPart.posRot, math.min(1,percent*rotPart.posRotFactor));
                        else
                            rx,ry,rz = Utils.vector3ArrayLerp(rotPart.defRot, rotPart.negRot, math.min(1,percent*rotPart.negRotFactor));
                        end;
                        setRotation(rotPart.node, rx,ry,rz);
                        if self.setMovingToolDirty ~= nil then
                            self:setMovingToolDirty(rotPart.node);
                        end;
                    end;
                end;
            end;

        end;
        self:setVehicleRpmUp(dt, revUp);
    end;
end;

function PaukAxis:draw()
end;

function PaukAxis:developmentReloadFromXML(xmlFile)
    PaukAxis.loadPaukAxis(self, xmlFile, true);
end;

function PaukAxis:setVehicleRpmUp(dt, isActive)
    if self.isMotorStarted and self.saveMinRpm ~= 0 then
        if dt ~= nil then
            if isActive == true then
                self.motor.minRpm = math.max(self.motor.minRpm-dt, -1000);
            else
                self.motor.minRpm = math.min(self.motor.minRpm+dt*2, self.saveMinRpm);
            end;
        else
            self.motor.minRpm = self.saveMinRpm;
        end;
        local fuelUsed = 0.0000011*math.abs(self.motor.minRpm);
        self:setFuelFillLevel(self.fuelFillLevel-fuelUsed);
        g_currentMission.missionStats:updateStats("fuelUsage", fuelUsed);
    end;
end;