--
-- ExtendedDynamicMountAttacher
--
-- @author  Stefan Maurus
-- @date  18/07/2019
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.

---Specialization to set the position of the cutter correctly on the cutter trailer
-- @category Specializations
ExtendedDynamicMountAttacher = {}

---Checks if all prerequisite specializations are loaded
-- @param table specializations specializations
-- @return boolean hasPrerequisite true if all prerequisite specializations are loaded
-- @includeCode
function ExtendedDynamicMountAttacher.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(DynamicMountAttacher, specializations);
end;

function ExtendedDynamicMountAttacher.registerOverwrittenFunctions(vehicleType)
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "addDynamicMountedObject", ExtendedDynamicMountAttacher.addDynamicMountedObject);
end;

function ExtendedDynamicMountAttacher.registerEventListeners(vehicleType)
    local functionNames = {
        "onLoad",
		"onUpdateTick"
	};

	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerEventListener(vehicleType, functionName, ExtendedDynamicMountAttacher);
	end;
end;

---
-- @includeCode
function ExtendedDynamicMountAttacher:onLoad(savegame)
    if FlieglTransportPackUtil == nil then
        return;
    end;
    
    local specDynamicMountAttacher = FlieglTransportPackUtil.getSpecByName(self, "dynamicMountAttacher");

    specDynamicMountAttacher.fixedPositions = {}

    local fixedPositionNumber = 0;

    while true do
        local posKey = string.format("vehicle.dynamicMountAttacher.fixedPosition(%d)", fixedPositionNumber);

        if not hasXMLProperty(self.xmlFile, posKey) then
            break;
        end;

        local entry = {};

        entry.xmlFilename = getXMLString(self.xmlFile, posKey .. "#xmlFilename");
        entry.jointNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, posKey .. "#jointNode"), self.i3dMappings);

        if entry.xmlFilename ~= nil and entry.jointNode ~= nil then
            table.insert(specDynamicMountAttacher.fixedPositions, entry);
        else
            g_logManager:xmlWarning(self.configFileName, "Could not load fixed position from '%s'", posKey);
        end;

        fixedPositionNumber = fixedPositionNumber + 1;
    end;
end;

---
-- @includeCode
function ExtendedDynamicMountAttacher:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
    if self.isServer then
        if self:getAllowDynamicMountObjects() then
            local specDynamicMountAttacher = FlieglTransportPackUtil.getSpecByName(self, "dynamicMountAttacher");

            if next(specDynamicMountAttacher.pendingDynamicMountObjects) ~= nil then
                self:raiseActive();
            end;
        end;
    end;
end;

---
-- @includeCode
function ExtendedDynamicMountAttacher:addDynamicMountedObject(superFunc, object)
    local specDynamicMountAttacher = FlieglTransportPackUtil.getSpecByName(self, "dynamicMountAttacher");

    if specDynamicMountAttacher.dynamicMountedObjects[object] == nil then
        superFunc(self, object);

        for fixedPositionNumber = 1, #specDynamicMountAttacher.fixedPositions do
            local position = specDynamicMountAttacher.fixedPositions[fixedPositionNumber];

            if StringUtil.endsWith(object.configFileName, position.xmlFilename) then
                if object.dynamicMountJointIndex ~= nil then
                    removeJoint(object.dynamicMountJointIndex);

                    object.dynamicMountJointIndex = nil;
                    object.dynamicMountObjectActorId = nil;
                    object.dynamicMountObject = nil;
                end;

                local x, y, z = getWorldTranslation(position.jointNode);
                local rx, ry, rz = getWorldRotation(position.jointNode);

                object:removeFromPhysics();
                specDynamicMountAttacher.pendingDynamicMountObjects[object] = nil; --## will be readded on addToPhysics

                object:setWorldPosition(x, y, z, rx, ry, rz, 1, true);
                object:addToPhysics();

                local trigger = specDynamicMountAttacher.dynamicMountAttacherTrigger;

                local couldMount = object:mountDynamic(self, trigger.rootNode, trigger.jointNode, trigger.mountType, trigger.forceAcceleration);

                if not couldMount then
                    self:removeDynamicMountedObject(object, false);
                end;
            end;
        end;
    else
        superFunc(self, object);
    end;
end;