--[[************************************************************************************************************************************************************
    
    extraRotatingParts v1.5.1 (compatible with MR)
    
    05/2014 © Saty MODS (Saty / http://forum.lsczech.cz)
    
****************************************************************************************************************************************************************
    
    (EN) INFO
    
    Free for use on mods. Modifications only with my permission !
    
    This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (Attribution / NonCommercial / NoDerivatives)
    http://creativecommons.org/licenses/by-nc-nd/4.0/deed.en
    
****************************************************************************************************************************************************************
    
    (CZ) INFO
    
    Pro volne pouziti v modech. ZAKAZ modifikaci bez meho souhlasu !
    
    Toto dilo podleha licenci : Creative Commons 4.0 International - Uvedte autora / Neuzivejte dilo komercne / Nezasahujte do dila 
    http://creativecommons.org/licenses/by-nc-nd/4.0/deed.cs
    
    --------------------------------------------------------------------------------------------------------------------------------------------------------    
    
    Zapis do XML souboru stroje :
    *****************************
    
    <extraRotatingParts>
        <motorRotatingParts acceleration="0.03" deceleration="0.0125" >
            <part node="2|24" rotAxis="1" speedFixed="-500" speedByMotor="1" />
            <part node="2|25" rotAxis="2" speedFixed="900" speedByMotor="1" />
            <part node="2|26" rotAxis="3" speedFixed="0" speedByMotor="1.5" />
        </motorRotatingParts>
        <threshingRotatingParts acceleration="0.03" deceleration="0.005" >
            <part node="6|8" rotAxis="1" speedFixed="-1100" />
            <part node="6|9" rotAxis="2" speedFixed="1100" />
        </threshingRotatingParts>
        <turnOnRotatingParts acceleration="0.03" deceleration="0.005" >
            <part node="8|0" rotAxis="1" speedFixed="-1000" />
            <part node="8|1" rotAxis="2" speedFixed="1000" />
        </turnOnRotatingParts>
        <driveRotatingParts>
            <part node="22|0" fromWheel="1" onlyAWD="false" />
        </driveRotatingParts>
    </extraRotatingParts>
    
    
    Vysvetlivky k funkcim:
    
    motorRotatingParts            - rotacni casti, ktere se toci pri nastartovanem motoru
    threshingRotatingParts            - rotacni casti, ktere se toci pri zapnutem drtici (funguje i pro listy kombajnu, atd.)
    turnOnRotatingParts            - rotacni casti, ktere se toci pri zapnutem nastroji s funkci turnOn
    driveRotatingParts            - rotacni casti, ktere se otaci pri jizde stejne s koly
    acceleration                - hodnota urcuje jak rychle se vsechny dane casti po zapnuti roztoci (pri nezadani defaultni hodnota "1" = okamzite roztoceni)
    deceleration                - hodnota urcuje jak rychle se vsechny dane casti po vypnuti zastavi (pri nezadani defaultni hodnota "1" = okamzite zastaveni)
    part                    - jednotlive casti (neomezeny pocet)
    node                    - index rotacni casti v GE
    rotAxis                    - osa otaceni [1=X; 2=Y; 3=Z] (pri nezadani defaultni hodnota "2" = osa Y)
    speedFixed                - hodnota pevnych otacek (cca v RPM) [hodnota s - je reverzni otaceni]
    speedByMotor                - nasobek, ktery urcuje hodnotu otacek casti podle otacek motoru [1 = 1:1 s motorem] (funguje pouze s hodnotou speedFixed="0")
    fromWheel                - kolo, podle ktereho se dana cast otaci (pri nezadani defaultni hodnota "1" = 1. kolo)
    onlyAWD                    - dana cast se otaci pouze pri zapnutem AWD/4x4 (pri nezadani defaultni hodnota "false" = otaci se stale)
    
    --------------------------------------------------------------------------------------------------------------------------------------------------------    
    
    Zapis do souboru modDesc.xml :
    ******************************
    
    vsadit do <specializations> :
        <specialization name="extraRotatingParts"  className="extraRotatingParts"  filename="scripts/extraRotatingParts.lua"/>
    
    vsadit do <vehicleTypes> :
        <specialization name="extraRotatingParts" />
    
************************************************************************************************************************************************************]]--

extraRotatingParts = {};

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

function extraRotatingParts:load(savegame)
    -- motor rotating parts
    self.motorRotatingParts = {};
    self.accelerationMRP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.motorRotatingParts#acceleration"), 1);
    self.decelerationMRP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.motorRotatingParts#deceleration"), 1);
    local i = 0;
    while true do
        local key = string.format("vehicle.extraRotatingParts.motorRotatingParts.part(%d)", i);
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
        local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#node"));
        local rotAxis = Utils.getNoNil(getXMLInt(xmlFile, key.."#rotAxis"), 2);
        local speedFixed = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedFixed"), 0);
        if speedFixed ~= 0 then
            speedFixed = math.rad(speedFixed * 0.001);
        end;
        local speedByMotor = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedByMotor"), 1);
        if node ~= nil then
            table.insert(self.motorRotatingParts, {node=node, rotAxis=rotAxis, speedFixed=speedFixed, speedByMotor=speedByMotor});
        end;
        i = i + 1;
    end;
    
    -- turnOn rotating parts
    self.turnOnRotatingParts = {};
    self.accelerationORP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.turnOnRotatingParts#acceleration"), 1);
    self.decelerationORP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.turnOnRotatingParts#deceleration"), 1);
    local i = 0;
    while true do
        local key = string.format("vehicle.extraRotatingParts.turnOnRotatingParts.part(%d)", i);
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
        local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#node"));
        local rotAxis = Utils.getNoNil(getXMLInt(xmlFile, key.."#rotAxis"), 2);
        local speedFixed = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedFixed"), 0)*0.001);
        if node ~= nil then
            table.insert(self.turnOnRotatingParts, {node=node, rotAxis=rotAxis, speedFixed=speedFixed});
        end;
        i = i + 1;
    end;
    
    -- threshing rotating parts
    self.threshingRotatingParts = {};
    self.accelerationTRP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.threshingRotatingParts#acceleration"), 1);
    self.decelerationTRP = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.extraRotatingParts.threshingRotatingParts#deceleration"), 1);
    local i = 0;
    while true do
        local key = string.format("vehicle.extraRotatingParts.threshingRotatingParts.part(%d)", i);
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
        local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#node"));
        local rotAxis = Utils.getNoNil(getXMLInt(xmlFile, key.."#rotAxis"), 2);
        local speedFixed = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedFixed"), 0)*0.001);
        if node ~= nil then
            table.insert(self.threshingRotatingParts, {node=node, rotAxis=rotAxis, speedFixed=speedFixed});
        end;
        i = i + 1;
    end;
    
    -- drive rotating parts
    self.driveRotatingParts = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.extraRotatingParts.driveRotatingParts.part(%d)", i);
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
        local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#node"));
        local wheel = Utils.getNoNil(getXMLInt(xmlFile, key.."#fromWheel"), 1);
        local awd = Utils.getNoNil(getXMLBool(xmlFile, key .. "#onlyAWD"), false);
        if node ~= nil then
            table.insert(self.driveRotatingParts, {node=node, wheel=wheel, awd=awd});
        end;
        i = i + 1;
    end;
    
    self.regSpeedMRP = 0;
    self.regSpeedORP = 0;
    self.regSpeedTRP = 0;
    
    self.cutterOverload = false;
end;

function extraRotatingParts:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)    
    if not resetVehicles then

    end; 
    return BaseMission.VEHICLE_LOAD_OK;
end;

function extraRotatingParts:getSaveAttributesAndNodes(nodeIdent)
    local attributes = "";
    return attributes, nil;
end;

function extraRotatingParts:update(dt)
end;

function extraRotatingParts:updateTick(dt)
    if self.motor ~= nil and self.isMotorStarted then
        if self.regSpeedMRP < 1 then
            self.regSpeedMRP = self.regSpeedMRP + self.accelerationMRP;
        else
            self.regSpeedMRP = 1;
        end;
        for _, node in pairs(self.motorRotatingParts) do
            if node.speedFixed ~= 0 then
                if node.rotAxis == 3 then
                    rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedMRP));
                elseif node.rotAxis == 1 then
                    rotate(node.node, dt * (node.speedFixed * self.regSpeedMRP), 0, 0);
                else
                    rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedMRP), 0);
                end;
            else
                local speed = {};
                if self.motor.isRealistic then
                    speed = math.rad(RealisticUtils.linearFx(self.realLastMotorFx^0.5, 300, 2300) * node.speedByMotor * 0.001);
                else
                    speed = math.rad(self.motor.lastMotorRpm * node.speedByMotor * 0.001);
                end;
                if node.rotAxis == 3 then
                    rotate(node.node, 0, 0, dt * (speed * self.regSpeedMRP));
                elseif node.rotAxis == 1 then
                    rotate(node.node, dt * (speed * self.regSpeedMRP), 0, 0);
                else
                    rotate(node.node, 0, dt * (speed * self.regSpeedMRP), 0);
                end;
            end;
        end;
    else
        if self.regSpeedMRP > 0 then
            self.regSpeedMRP = self.regSpeedMRP - self.decelerationMRP;
            for _, node in pairs(self.motorRotatingParts) do
                if node.speedFixed ~= 0 then
                    if node.rotAxis == 3 then
                        rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedMRP));
                    elseif node.rotAxis == 1 then
                        rotate(node.node, dt * (node.speedFixed * self.regSpeedMRP), 0, 0);
                    else
                        rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedMRP), 0);
                    end;
                else
                    local speed = {};
                    if self.motor.isRealistic then
                        speed = math.rad(RealisticUtils.linearFx(self.realLastMotorFx^0.5, 300, 2300) * node.speedByMotor * 0.001);
                    else
                        speed = math.rad(self.motor.lastMotorRpm * node.speedByMotor * 0.001);
                    end;
                    if node.rotAxis == 3 then
                        rotate(node.node, 0, 0, dt * (speed * self.regSpeedMRP));
                    elseif node.rotAxis == 1 then
                        rotate(node.node, dt * (speed * self.regSpeedMRP), 0, 0);
                    else
                        rotate(node.node, 0, dt * (speed * self.regSpeedMRP), 0);
                    end;
                end;
            end;
        else
            self.regSpeedMRP = 0;
        end;
    end;

    if self.isTurnedOn or self.isRefillTurnOn or self.isBackSaleTurnOn then
        if self.regSpeedORP < 1 then
            self.regSpeedORP = self.regSpeedORP + self.accelerationORP;
        else
            self.regSpeedORP = 1;
        end;
        for _, node in pairs(self.turnOnRotatingParts) do
            if node.rotAxis == 3 then
                rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedORP));
            elseif node.rotAxis == 1 then
                rotate(node.node, dt * (node.speedFixed * self.regSpeedORP), 0, 0);
            else
                rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedORP), 0);
            end;
        end;
    else
        if self.regSpeedORP > 0 then
            self.regSpeedORP = self.regSpeedORP - self.decelerationORP;
            for _, node in pairs(self.turnOnRotatingParts) do
                if node.rotAxis == 3 then
                    rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedORP));
                elseif node.rotAxis == 1 then
                    rotate(node.node, dt * (node.speedFixed * self.regSpeedORP), 0, 0);
                else
                    rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedORP), 0);
                end;
            end;
        else
            self.regSpeedORP = 0;
        end;
    end;
    
    if not self.cutterOverload and (self.isThreshing or self.reelStarted) then
        if self.regSpeedTRP < 1 then
            self.regSpeedTRP = self.regSpeedTRP + self.accelerationTRP;
        else
            self.regSpeedTRP = 1;
        end;
        for _, node in pairs(self.threshingRotatingParts) do
            if node.rotAxis == 3 then
                rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedTRP));
            elseif node.rotAxis == 1 then
                rotate(node.node, dt * (node.speedFixed * self.regSpeedTRP), 0, 0);
            else
                rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedTRP), 0);
            end;
        end;
    elseif self.cutterOverload then
        local regSpeed = math.random(0, 70) * 0.01;
        for _, node in pairs(self.threshingRotatingParts) do
            if node.rotAxis == 3 then
                rotate(node.node, 0, 0, dt * (node.speedFixed * regSpeed));
            elseif node.rotAxis == 1 then
                rotate(node.node, dt * (node.speedFixed * regSpeed), 0, 0);
            else
                rotate(node.node, 0, dt * (node.speedFixed * regSpeed), 0);
            end;
        end;
        self.regSpeedTRP = 0;
    else
        if self.regSpeedTRP > 0 then
            self.regSpeedTRP = self.regSpeedTRP - self.decelerationTRP;
            for _, node in pairs(self.threshingRotatingParts) do
                if node.rotAxis == 3 then
                    rotate(node.node, 0, 0, dt * (node.speedFixed * self.regSpeedTRP));
                elseif node.rotAxis == 1 then
                    rotate(node.node, dt * (node.speedFixed * self.regSpeedTRP), 0, 0);
                else
                    rotate(node.node, 0, dt * (node.speedFixed * self.regSpeedTRP), 0);
                end;
            end;
        else
            self.regSpeedTRP = 0;
        end;
    end;
    
    if self.driveRotatingParts ~= nil and self.wheels ~= nil then
        for _, node in pairs(self.driveRotatingParts) do
            if not node.awd or self.AllradV4Active or self.realAWDModeOn then
                local x1, y1, z1 = getRotation(self.wheels[node.wheel].driveNode);
                local x2, y2, z2 = getRotation(node.node);
                setRotation(node.node, x1, y2, z2);
            end;
        end;
    end;
end;

function extraRotatingParts:delete()
end;

function extraRotatingParts:readStream(streamId, connection)
end;

function extraRotatingParts:writeStream(streamId, connection)
end;

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

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

function extraRotatingParts:draw()
end;

function extraRotatingParts:onDeactivate()
end;