"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var ig_utilities_1 = require("@intelligentgraphics/ig.utilities");
var IGXC_1 = require("./IGXC");
var Hierarchy_1 = require("./Hierarchy");
var Logger_1 = tslib_1.__importDefault(require("./Logger"));
var Logger = Logger_1.default.createSubLogger("IGXCWriter");
var defaultOptions = {
    Recurse: true,
    StandardInteractors: false,
    ReplaceMaterialCategories: false,
    AddMaterialDefinitions: false,
    OfmlGeometries: false,
};
exports.getMergedIGXC = function (api, componentIds, rawOptions) {
    var tOptions = createOptions(rawOptions);
    // the merged IGXC:
    var tIGXC = IGXC_1.createScene();
    // the roots to operate on:
    var tRootIds = componentIds;
    if (!tRootIds) {
        tRootIds = api.GetRoots();
    }
    var tRoot = IGXC_1.createObject(IGXC_1.OBJECT_ROOT_PATH);
    tRoot.Selectable = "Self";
    tIGXC.Objects.push(tRoot);
    // TODO maybe this should be set from options some day:
    var tGeometrySubPath = function (geometry) {
        return geometry + ".geo/standard.obj";
    };
    var tRootCnt = 1;
    if (tRootIds) {
        tRootIds.forEach(function (rootId) {
            if (rootId.indexOf(Hierarchy_1.RootPostfix) === -1) {
                Logger.warn("Ignoring component " + rootId);
                return;
            }
            var tScene = exports.getAsIGXC(api, rootId, tOptions);
            var tCount = tRootCnt++;
            // Process components:
            tScene.Objects.forEach(function (object) {
                var tRelPath = object.Path;
                // Shift the path one level down:
                object.Path =
                    tRelPath === "."
                        ? "o" + tCount
                        : "o" + tCount + "." + object.Path;
                var tComponentId = tRelPath === "."
                    ? rootId
                    : rootId.substring(0, rootId.length - 1) + tRelPath;
                var tPosition = api.GetPosition(tComponentId);
                var tXRotation = api.GetXRotation(tComponentId);
                var tYRotation = api.GetYRotation(tComponentId);
                var tZRotation = api.GetZRotation(tComponentId);
                var tScaling = api.GetScaling(tComponentId);
                object.Transform = {
                    Position: {
                        X: tPosition.x,
                        Y: tPosition.y,
                        Z: tPosition.z,
                    },
                    Rotation: {
                        X: Math.round(tXRotation),
                        Y: Math.round(tYRotation),
                        Z: Math.round(tZRotation),
                    },
                    Scale: {
                        X: tScaling.x,
                        Y: tScaling.y,
                        Z: tScaling.z,
                    },
                };
                // GetAsIGXC() does not provide a Geometry dictionary:
                if (object.Geometry &&
                    tIGXC.Geometries[object.Geometry] === undefined) {
                    tIGXC.Geometries[object.Geometry] = tGeometrySubPath(object.Geometry);
                }
            });
            // Add components:
            tIGXC.Objects = tIGXC.Objects.concat(tScene.Objects);
            // Merge material categories:
            for (var tKey in tScene.Categories) {
                if (!tIGXC.Categories[tKey]) {
                    tIGXC.Categories[tKey] = tScene.Categories[tKey];
                }
            }
            // Merge materials:
            for (var tKey in tScene.Materials) {
                if (!tIGXC.Materials[tKey]) {
                    tIGXC.Materials[tKey] = tScene.Materials[tKey];
                }
            }
            /* GetAsIGXC() does not provide a Geometry dictionary:
            // Merge geometries:
            for (let tKey in tScene.Geometries) {
                if (!tIGXC.Geometries[tKey]) {
                    tIGXC.Geometries[tKey] = tGeometrySubPath(tKey);
                }
            }
            */
        });
    }
    return tIGXC;
};
exports.getAsIGXC = function (api, componentId, rawOptions) {
    var e_1, _a;
    var options = createOptions(rawOptions);
    var tRoot = componentId;
    var tPrefixPath = Hierarchy_1.isRootGfxId(componentId)
        ? componentId.substring(0, componentId.length - 1)
        : componentId + ".";
    var resultIGXC = IGXC_1.createScene();
    resultIGXC.Objects.push(createIGXCObject(api, resultIGXC, tPrefixPath, componentId, true, options));
    if (options.Recurse) {
        var tChildToIGXC_1 = function (componentId) {
            var e_2, _a;
            var tRepresentation = createIGXCObject(api, resultIGXC, tPrefixPath, componentId, false, options);
            if (!tRepresentation) {
                return;
            }
            resultIGXC.Objects.push(tRepresentation);
            var tChildren = api.GetChildren(componentId);
            try {
                for (var tChildren_1 = tslib_1.__values(tChildren), tChildren_1_1 = tChildren_1.next(); !tChildren_1_1.done; tChildren_1_1 = tChildren_1.next()) {
                    var child = tChildren_1_1.value;
                    tChildToIGXC_1(child);
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (tChildren_1_1 && !tChildren_1_1.done && (_a = tChildren_1.return)) _a.call(tChildren_1);
                }
                finally { if (e_2) throw e_2.error; }
            }
        };
        var tComponentChildren = api.GetChildren(componentId);
        try {
            for (var tComponentChildren_1 = tslib_1.__values(tComponentChildren), tComponentChildren_1_1 = tComponentChildren_1.next(); !tComponentChildren_1_1.done; tComponentChildren_1_1 = tComponentChildren_1.next()) {
                var child = tComponentChildren_1_1.value;
                tChildToIGXC_1(child);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (tComponentChildren_1_1 && !tComponentChildren_1_1.done && (_a = tComponentChildren_1.return)) _a.call(tComponentChildren_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
    }
    if (resultIGXC.Objects && !options.OfmlGeometries) {
        var Geometries_1 = {};
        resultIGXC.Objects.forEach(function (ob) {
            if (ob.Geometry) {
                Geometries_1[ob.Geometry] = api.GeometryLinks[ob.Geometry];
            }
        });
        resultIGXC.Geometries = Geometries_1;
    }
    return resultIGXC;
};
var createIGXCObject = function (api, igxc, prefixPath, componentId, rootLevel, options) {
    if (rootLevel === void 0) { rootLevel = false; }
    if (!rootLevel && api.GetVisibility(componentId) === false) {
        return;
    }
    var tObject = IGXC_1.createObject(rootLevel ? "." : componentId.replace(prefixPath, ""));
    tObject.Selectable = api.GetSelectionMode(componentId);
    tObject.Categories = api.GetCategories(componentId);
    tObject.Layer = ig_utilities_1.valueOrDefault(api.GetLayer(componentId), undefined);
    tObject.Points = api.GetPoints(componentId).map(function (point) { return ({
        Key: point.key,
        Foreign: point.foreign,
        Type: point.type,
        Enabled: point.enabled,
        Point: {
            X: point.point.x,
            Y: point.point.y,
            Z: point.point.z,
        },
        Rotation: {
            X: point.rotation.x,
            Y: point.rotation.y,
            Z: point.rotation.z,
        },
        Representation: point.representation,
    }); });
    var tPosition = api.GetPosition(componentId);
    var tXRotation = api.GetXRotation(componentId);
    var tYRotation = api.GetYRotation(componentId);
    var tZRotation = api.GetZRotation(componentId);
    var tScaling = api.GetScaling(componentId);
    if (rootLevel === false) {
        tObject.Transform = {
            Position: {
                X: tPosition.x,
                Y: tPosition.y,
                Z: tPosition.z,
            },
            Rotation: {
                X: Math.round(tXRotation),
                Y: Math.round(tYRotation),
                Z: Math.round(tZRotation),
            },
            Scale: {
                X: tScaling.x,
                Y: tScaling.y,
                Z: tScaling.z,
            },
        };
    }
    var tGeometry = api.GetGeometry(componentId);
    if (tGeometry) {
        //console.log(tObject,  tGeometry);
        if (options.OfmlGeometries) {
            var tScope = tGeometry.substring(0, tGeometry.lastIndexOf(".") + 1);
            var tNewScope = tScope.replace(".", "_");
            tNewScope = tNewScope.replace(".", "_");
            tNewScope = tNewScope.replace(".", "_");
            tNewScope = tNewScope + "D3_";
            tGeometry = tGeometry.replace(tScope, tNewScope).toLowerCase();
        }
        tObject.Geometry = tGeometry;
    }
    var materialName = api.GetMaterial(componentId);
    if (materialName && !igxc.Materials[materialName]) {
        var material = api.Materials[materialName];
        if (material) {
            igxc.Materials[materialName] = material;
        }
    }
    var tMaterialCategory = api.GetMaterialCategory(componentId);
    if (materialName) {
        if (tMaterialCategory && tMaterialCategory[0] !== "@") {
            if (options.ReplaceMaterialCategories) {
                tObject.MaterialCategory = "@" + materialName;
            }
            else {
                tObject.MaterialCategory = tMaterialCategory;
            }
            // In case of non-implicit material category dump the material too.
            tObject.Material = materialName;
        }
        else {
            // here, "@" + tMat should be the same as tMatCat
            tObject.MaterialCategory = "@" + materialName;
        }
    }
    else if (tMaterialCategory) {
        tObject.MaterialCategory = tMaterialCategory;
        if (tMaterialCategory[0] !== "@") {
            // In case of non-implicit material category dump the material too.
            tObject.Material = ig_utilities_1.valueOrDefault(materialName, undefined);
        }
    }
    tObject.Layer = ig_utilities_1.valueOrDefault(api.GetLayer(componentId), undefined);
    var tEvaluator = api.GetEvaluator(componentId);
    if (tEvaluator) {
        tObject.Evaluator = tEvaluator["Type"];
        var tParameters = {};
        for (var tKey in tEvaluator) {
            if (tKey === "Type") {
                continue;
            }
            if (tEvaluator.hasOwnProperty(tKey)) {
                tParameters[tKey] = tEvaluator[tKey];
            }
        }
        tObject.EvaluatorParameters = tParameters;
    }
    var tInteractor = api.GetInteractor(componentId);
    if (tInteractor) {
        var tInteractorType = tInteractor["Type"];
        if (options.StandardInteractors === false ||
            tInteractorType.indexOf("IGX.Std") === 0) {
            tObject.Interactor = tInteractorType;
            var tParameters = {};
            for (var tKey in tInteractor) {
                if (tKey === "Type") {
                    continue;
                }
                if (tKey === "id") {
                    continue;
                }
                if (tInteractor.hasOwnProperty(tKey)) {
                    tParameters[tKey] = tInteractor[tKey];
                }
            }
            tObject.InteractorParameters = tParameters;
        }
    }
    return tObject;
};
var createOptions = function (userOptions) { return (tslib_1.__assign(tslib_1.__assign({}, defaultOptions), userOptions)); };
