import { __values } from "tslib";
import { isNullOrUndefined, isValue, } from "@intelligentgraphics/ig.utilities";
import Logger from "../Logger";
import * as IGXC from "../IGXC";
import { createQuaternion, MathUtils, createEulerFromQuaternion, } from "../Math";
import { Category } from "../Category";
export var preProcessIGXC = function (igxc, api, superRootId) {
    var e_1, _a;
    var validatedIGXC = IGXC.createScene();
    for (var key in igxc) {
        var value = igxc[key];
        if (isValue(value)) {
            validatedIGXC[key] = value;
        }
    }
    for (var index = 0; index < validatedIGXC.Objects.length; index++) {
        var rawObject = validatedIGXC.Objects[index];
        if (isNullOrUndefined(rawObject.Path)) {
            throw new Error("Refusing to load igxc, because the object at index \"" + index + "\" is missing a path!");
        }
        var validatedObject = IGXC.createObject(rawObject.Path);
        validatedIGXC.Objects[index] = validatedObject;
        for (var key in rawObject) {
            var value = rawObject[key];
            if (isValue(value)) {
                validatedObject[key] = value;
            }
        }
    }
    try {
        for (var _b = __values(validatedIGXC.Objects), _c = _b.next(); !_c.done; _c = _b.next()) {
            var object = _c.value;
            preProcessNodeData(object, validatedIGXC, api, superRootId);
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return validatedIGXC;
};
var preProcessNodeData = function (node, igxc, api, superRootId) {
    if (!node.Material && node.MaterialCategory) {
        var tAtPosition = node.MaterialCategory.indexOf("@");
        if (tAtPosition === 0) {
            // implicit material category, skip first char:
            node.Material = node.MaterialCategory.substring(1);
        }
        else if (tAtPosition > 0) {
            // Deprecated. To be removed sooner or later.
            // concatenation of material and category:
            Logger.warn("Deprecated Material Assignment: " + node.MaterialCategory + " in " + superRootId);
            var tMaterialCategory = node.MaterialCategory.substring(tAtPosition + 1);
            node.Material = node.MaterialCategory.substring(0, tAtPosition);
            node.MaterialCategory = tMaterialCategory;
        }
        else {
            node.Material = igxc.Categories[node.MaterialCategory];
        }
    }
    node.Categories = sanitizeObjectCategories(node.Categories);
    if (!isNullOrUndefined(node.Transform) &&
        !isNullOrUndefined(node.Transform.Rotation)) {
        var rotationNode = node.Transform.Rotation;
        if ("W" in rotationNode) {
            var quaternion = createQuaternion(rotationNode.X, rotationNode.Y, rotationNode.Z, rotationNode.W);
            var euler = createEulerFromQuaternion(quaternion, "xyz");
            rotationNode.X = MathUtils.radToDeg(euler.x);
            rotationNode.Y = MathUtils.radToDeg(euler.y);
            rotationNode.Z = MathUtils.radToDeg(euler.z);
            delete rotationNode.W;
        }
        if ((rotationNode.X !== 0 && rotationNode.Y !== 0) ||
            (rotationNode.Y !== 0 && rotationNode.Z !== 0) ||
            (rotationNode.X !== 0 && rotationNode.Z !== 0)) {
            Logger.warn("Node " + node.Path + " in " + superRootId + ": only 1 rotation allowed, invalid: " + rotationNode.X + ", " + rotationNode.Y + ", " + rotationNode.Z);
        }
    }
    if (node.Geometry) {
        if (igxc.Geometries) {
            if (Object.keys(igxc.Geometries).indexOf(node.Geometry) < 0) {
                console.warn('Geometry "' +
                    node.Geometry +
                    '" of "' +
                    node.Path +
                    '" does not exist in .Geometries');
                node.Geometry = undefined;
            }
            else {
                api.GeometryLinks[node.Geometry] =
                    igxc.Geometries[node.Geometry];
            }
        }
        else {
            console.warn(".Geometry set for" +
                node.Path +
                " but no global .Geometries entry ?");
        }
    }
};
/**
 * while importing categories support now string[] as well as string and normalize to lowercase except standardized "durchWand"
 * @param input
 */
var sanitizeObjectCategories = function (input) {
    if (isNullOrUndefined(input)) {
        return undefined;
    }
    var tTemp = [];
    if (typeof input === "string") {
        tTemp = input.split(",");
    }
    else {
        // array
        tTemp = input;
    }
    return tTemp
        .map(function (rawCategory) {
        var lowerCaseCategory = rawCategory.toLowerCase();
        if (rawCategory === Category.CuttingThroughWall) {
            return rawCategory;
        }
        if (rawCategory !== lowerCaseCategory) {
            Logger.info("ObjectCategories: \"" + input + "\" must be lowercase! \"" + rawCategory + "\" modified to \"" + lowerCaseCategory + "\"");
            return lowerCaseCategory;
        }
        return rawCategory;
    })
        .join(",");
};
