--
-- TerraTrac for FS22
-- @author:    	Fredzaza, fs22 taz
-- @history:	v1.0 - 2019-06-28 - converted to FS19
--

TerraTrac = {};
TerraTrac.modDirectory = g_currentModDirectory;

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

function TerraTrac.registerEventListeners(vehicleType)
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", TerraTrac)
	SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", TerraTrac)
    SpecializationUtil.registerEventListener(vehicleType, "onUpdate", TerraTrac)
    SpecializationUtil.registerEventListener(vehicleType, "onDraw", TerraTrac)
	SpecializationUtil.registerEventListener(vehicleType, "onLeave", TerraTrac)
end

function TerraTrac:onLoad(savegame)
	self.spec_terraTrac = {}
	local spec = self.spec_terraTrac
	local xmlFile = self.xmlFile
	
	spec.indexTracRight = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TracWheelsRight#index"));    
    spec.charIdAnimR = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TracWheelsRight#node"));
    spec.clipIndexAnimR = getXMLString(xmlFile, "vehicle.TracWheelsRight#animationClip");
    spec.spedR = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.TracWheelsRight#sped"))
    spec.TracWheelsRight = {}
    local i = 0
    while true do
        local baseName = string.format("vehicle.TracWheelsRight.rotatingPart(%d)", i)
        local index = getXMLString(xmlFile, baseName .. "#index")
        if index == nil then
            break
        end
        local node = I3DUtil.indexToObject(self.components, index)
        if node ~= nil then
            local entry = {}
            entry.node = node
            entry.speedScale = getXMLFloat(xmlFile, baseName .. "#speedScale")
            if entry.speedScale == nil then
                entry.speedScale = 1 / Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#radius"), 1)
            end
            table.insert(spec.TracWheelsRight, entry)
        end
        i = i + 1        
    end
    
    spec.indexTracLeft = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TracWheelsLeft#index"));    
    spec.charIdAnimL = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, "vehicle.TracWheelsLeft#node"));
    spec.clipIndexAnimL = getXMLString(xmlFile, "vehicle.TracWheelsLeft#animationClip");
    spec.spedL = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.TracWheelsLeft#sped"))        
    spec.TracWheelsLeft = {}
    local i = 0
    while true do
        local baseName = string.format("vehicle.TracWheelsLeft.rotatingPart(%d)", i)
        local index = getXMLString(xmlFile, baseName .. "#index")
        if index == nil then
            break
        end
        local node = I3DUtil.indexToObject(self.components, index)
        if node ~= nil then
            local entry = {}
            entry.node = node
            entry.speedScale = getXMLFloat(xmlFile, baseName .. "#speedScale")
            if entry.speedScale == nil then
                entry.speedScale = 1 / Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#radius"), 1)
            end
            table.insert(spec.TracWheelsLeft, entry)
        end
        i = i + 1        
    end
end

function TerraTrac:onPostLoad(savegame)
	local spec = self.spec_terraTrac
end

function TerraTrac:onUpdate(dt, vehicle)
	local spec = self.spec_terraTrac
	local movingDirectionR = 0; 
	local movingDirectionL = 0;   
    if self.spec_motorized.isMotorStarted then
        local newX1, newY1, newZ1 = getWorldTranslation(spec.indexTracLeft);
        if spec.lastTranslationL == nil then
            spec.lastTranslationL = {newX1, newY1, newZ1};
        end;
        local dx1, dy1, dz1 = worldDirectionToLocal(spec.indexTracLeft, newX1-spec.lastTranslationL[1], newY1-spec.lastTranslationL[2], newZ1-spec.lastTranslationL[3]);
        local movingDirectionL = 0
        if self.spec_motorized.lastSpeedReal > 1.0E-5 then    
            if dz1 < 1.0E-4 then
                movingDirectionL = -1;
            elseif dz1 > 1.0E-4 then
                movingDirectionL = 1;    
            end;
        end;    
        local lastMovedDistanceL = MathUtil.vector3Length(dx1, dy1, dz1);
        spec.lastTranslationL[1] = newX1
        spec.lastTranslationL[2] = newY1
        spec.lastTranslationL[3] = newZ1
    
        local charIdL = getAnimCharacterSet(spec.charIdAnimL);
        local clipIndexL = getAnimClipIndex(charIdL, spec.clipIndexAnimL);
		
        assignAnimTrackClip(charIdL , 0, clipIndexL);
        setAnimTrackLoopState(charIdL, 0, true);
        setAnimTrackSpeedScale(charIdL, 0, spec.spedL*lastMovedDistanceL*movingDirectionL);
        enableAnimTrack(charIdL, 0);

        for _, v in pairs(spec.TracWheelsLeft) do
            rotate(v.node, v.speedScale * lastMovedDistanceL*movingDirectionL, 0, 0)
        end    

        local newX2, newY2, newZ2 = getWorldTranslation(spec.indexTracRight);
        if spec.lastTranslationR == nil then
            spec.lastTranslationR = {newX2, newY2, newZ2};
        end;
        local dx2, dy2, dz2 = worldDirectionToLocal(spec.indexTracRight, newX2-spec.lastTranslationR[1], newY2-spec.lastTranslationR[2], newZ2-spec.lastTranslationR[3]);
        local movingDirectionR = 0
        if self.spec_motorized.lastSpeedReal > 1.0E-5 then    
            if dz2 < 1.0E-4 then
                movingDirectionR = -1;
            elseif dz2 > 1.0E-4 then
                movingDirectionR = 1;        
            end;
        end;    
        local lastMovedDistanceR = MathUtil.vector3Length(dx2, dy2, dz2);    
        spec.lastTranslationR[1] = newX2
        spec.lastTranslationR[2] = newY2
        spec.lastTranslationR[3] = newZ2    
        
        local charIdR = getAnimCharacterSet(spec.charIdAnimR);
        local clipIndexR = getAnimClipIndex(charIdR, spec.clipIndexAnimR);        

        assignAnimTrackClip(charIdR , 0, clipIndexR);
        setAnimTrackLoopState(charIdR, 0, true);
        setAnimTrackSpeedScale(charIdR, 0, spec.spedR*lastMovedDistanceR*movingDirectionR);
        enableAnimTrack(charIdR, 0);
    
        for _, v in pairs(spec.TracWheelsRight) do
            rotate(v.node, v.speedScale * lastMovedDistanceR*movingDirectionR, 0, 0)
        end; 
    end;
end

function TerraTrac:onDraw()
	local spec = self.spec_terraTrac
end

function TerraTrac:onLeaveVehicle()
end;