/// <reference path="resources/three.d.ts" />
/// <reference path="FDGeomObject.ts" />
/// <reference path="debugPrinter.ts" />
var FD;
(function (FD) {
    var FDNode = (function () {
        /**
        * Creates a new instance of FDnode. Creates am empty object to be added to the scene graph. And possitions it at its origin
        * @class FDNode
        * @classdesc Container for Nodes
        */
        function FDNode() {
            this.nodeSceneGraph = new THREE.Object3D();
            this.nodeSceneGraph.position = new THREE.Vector3(0, 0, 0);
            this.children = [];
            this.siblings = [];
            this.geometryObjects = [];
        }
        /**
        * Sets additional data to the node.
        * @memberof FDNode
        * @function setData
        * @param {Object} data
        */
        FDNode.prototype.setData = function (data) {
            this.data = data;
        };

        /**
        * Returns the data object
        * @memberof FDNode
        * @function getData
        */
        FDNode.prototype.getData = function () {
            return this.data;
        };

        /**
        * Add a child node. Adds the node to the correct possition in the scenegraph
        * @memberof FDNode
        * @function addChild
        * @param {FDNode} child
        */
        FDNode.prototype.addChild = function (child) {
            this.children.push(child);
            this.nodeSceneGraph.add(child.getNodeSceneGraph());
        };

        /**
        * Add a sibling node.
        * @memberof FDNode
        * @function addSibling
        * @param {FDNode} sibling
        */
        FDNode.prototype.addSibling = function (sibling) {
            this.siblings.push(sibling);
        };

        /**
        * Set the unique identifier for this node
        * @memberof FDNode
        * @function setUniqueId
        * @param {String} uid
        */
        FDNode.prototype.setUniqueId = function (uid) {
            this.uniqueId = uid;
        };

        /**
        * returns the unique id
        * @memberof FDNode
        * @function getUniqueId
        * @returns {String} uid
        */
        FDNode.prototype.getUniqueId = function () {
            return this.uniqueId;
        };

        /**
        * returns an array of its children
        * @memberof FDNode
        * @function getChildren
        * @returns {FDNode[]} children
        */
        FDNode.prototype.getChildren = function () {
            return this.children;
        };

        /**
        * Sets the parent of this node. Does NOT update the scene graph
        * @memberof FDNode
        * @function setParent
        * @param {FDNode} parent
        */
        FDNode.prototype.setParent = function (parent) {
            this.parent = parent;
        };

        /**
        * Get the parent node
        * @memberof FDNode
        * @function getParent
        * @returns {FDNode} parent
        */
        FDNode.prototype.getParent = function () {
            return this.parent;
        };

        /**
        * Applies the matrix to this entry in the scene graph
        * @memberof FDNode
        * @function transform
        * @param {THREE.Matrix4} matrix
        */
        FDNode.prototype.transform = function (matrix) {
            this.nodeSceneGraph.applyMatrix(matrix);
        };

        /**
        * Returns the node in the scenegraph
        * @memberof FDNode
        * @function getNodeSceneGraph
        * @returns {THREE.Object3D} scene graph node
        */
        FDNode.prototype.getNodeSceneGraph = function () {
            return this.nodeSceneGraph;
        };

        /**
        * Returns all the ids of all meshes in this node of the scene graph
        * @memberof FDNode
        * @function getMeshIds
        * @returns Array of mesh Ids
        */
        FDNode.prototype.getMeshIds = function () {
            var meshIds = [];
            for (var m in this.geometryObjects) {
                meshIds.push(this.geometryObjects[m].geometry.id);
            }
            return meshIds;
        };

        /**
        * Rotates the scene graph node around the axis
        * @memberof FDNode
        * @function rotate
        * @param {number} angle in rad
        * @param {THREE.Vector3} axis
        */
        FDNode.prototype.rotate = function (angle, axis) {
            var matrix = new THREE.Matrix4().makeRotationAxis(axis, angle);

            this.nodeSceneGraph.updateMatrixWorld(true);
            this.nodeSceneGraph.applyMatrix(matrix);
        };

        /**
        * Rotates the meshes of this node individually.
        * @memberof FDNode
        * @function rotateLocal
        * @param {number} angle in rad
        * @param {THREE.Vector3} axis
        */
        FDNode.prototype.rotateLocal = function (angle, axis) {
            var matrix = new THREE.Matrix4().makeRotationAxis(axis, angle);
            this.nodeSceneGraph.updateMatrixWorld(true);
            for (var c in this.nodeSceneGraph.children) {
                this.nodeSceneGraph.children[c].applyMatrix(matrix);
            }
        };

        /**
        * Returns an array of meshes in this node
        * @memberof FDNode
        * @function getAllGeometry
        * @returns {THREE.Mesh[]} geometry
        */
        FDNode.prototype.getAllGeometry = function () {
            return this.geometryObjects;
        };

        /**
        * Add a mesh to the node
        * @memberof FDNode
        * @function addGeometry
        * @param {THREE.Mesh} geomObject
        */
        FDNode.prototype.addGeometry = function (geomObject) {
            this.geometryObjects.push(geomObject);
            this.nodeSceneGraph.add(geomObject);
        };

        /**
        * Sets the possition of the node relative to its position in the scenegraph.
        * @memberof FDNode
        * @function setPosition
        * @param {THREE.Vector3} position
        */
        FDNode.prototype.setPosition = function (position) {
            this.nodeSceneGraph.position = position;
        };

        /**
        * Returns current position of the node relative to its position in the scene graph
        * @memberof FDNode
        * @function getPosition
        * @returns {THREE.Vector3} position
        */
        FDNode.prototype.getPosition = function () {
            return this.nodeSceneGraph.position;
        };

        /**
        * Returns current position of the node in world space
        * @memberof FDNode
        * @function getWorldCoordinates
        * @returns {THREE.Vector3} position
        */
        FDNode.prototype.getWorldCoordinates = function () {
            var vec = new THREE.Vector3();
            vec.getPositionFromMatrix(this.nodeSceneGraph.matrixWorld);
            return vec;
        };
        return FDNode;
    })();
    FD.FDNode = FDNode;
})(FD || (FD = {}));
