import "scejs";
import {Graph} from "./Graph.class";
import {Resources} from "./resources";

/**
 * @class
 */
export class GRel {
    constructor(jsonIn) {
        let target = document.createElement("div");
        document.getElementsByTagName("body")[0].appendChild(target);

        target.id = "elQUBitJS";
        target.style.width = "950px";
        target.innerHTML = `<div></div>`;


        jsonIn.target = target;
        jsonIn.dimensions = {"width": 500, "height": 500};
        jsonIn.enableUI = true;

        this.nodeValues = [];
        this.lastNodeValues = [];
        this.nodeValuesB = [];
        this.lastNodeValuesB = [];
        this.nodeValuesC = [];
        this.lastNodeValuesC = [];
        this.nodeValuesD = [];
        this.lastNodeValuesD = [];
        this.nodeValuesE = [];
        this.lastNodeValuesE = [];
        this.nodeValuesF = [];
        this.lastNodeValuesF = [];

        this.nodeTypes = [];

        this.sce = new SCE();
        this.sce.initialize(jsonIn);

        this.project = new Project();
        this.sce.loadProject(this.project);

        let stage = new Stage();
        stage.setBackgroundColor([0.0,0.0,0.0,1.0]);
        this.project.addStage(stage);
        this.project.setActiveStage(stage);

        // CAMERA
        let simpleCamera = new SimpleCamera(this.sce);
        simpleCamera.setView(Constants.VIEW_TYPES.TOP);
        simpleCamera.setVelocity(1.0);
        this.sce.setDimensions(jsonIn.dimensions.width, jsonIn.dimensions.height);

        this.graph = new Graph(this.sce,{"enableFonts":true});
        this.graph.enableNeuronalNetwork();
        this.graph.layerCount = 2;
        this.graph.batch_repeats = (jsonIn.batch_repeats !== undefined && jsonIn.batch_repeats !== null) ? jsonIn.batch_repeats : 1;

        this.mesh_nodes = (this._geometryLength === 1) ? new Mesh().loadPoint() : new Mesh().loadQuad(4.0, 4.0);
    }

    nodeLogic(code) {
        this.graph.nodeLogic = code;
    }

    nodeVertexVisualization(code) {
        this.graph.nodeVertexVisualization = code;
    }

    nodeFragmentVisualization(code) {
        this.graph.nodeFragmentVisualization = code;
    }

    init() {
        this.graph.createWebGLBuffers();
        this.graph.enableForceLayout();
    }

    setValue(nodeName, value, idValue) {
        if(idValue === undefined || idValue === null || idValue === 0)
            this.nodeValues[this.graph._nodesByName[nodeName].nodeId] = value;
        else if(idValue === 1)
            this.nodeValuesB[this.graph._nodesByName[nodeName].nodeId] = value;
        else if(idValue === 2)
            this.nodeValuesC[this.graph._nodesByName[nodeName].nodeId] = value;
        else if(idValue === 3)
            this.nodeValuesD[this.graph._nodesByName[nodeName].nodeId] = value;
        else if(idValue === 4)
            this.nodeValuesE[this.graph._nodesByName[nodeName].nodeId] = value;
        else if(idValue === 5)
            this.nodeValuesF[this.graph._nodesByName[nodeName].nodeId] = value;
    }

    /**
     * @param {Object} jsonIn
     * @param {String} jsonIn.name
     * @param {number} [jsonIn.nodeValue]
     * @param {number} [jsonIn.nodeValueB]
     * @param {number} [jsonIn.nodeValueC]
     * @param {number} [jsonIn.nodeValueD]
     * @param {number} [jsonIn.nodeValueE]
     * @param {number} [jsonIn.nodeValueF]
     * @param {int} jsonIn.nodeType
     * @param {Array<number>} [jsonIn.destination=[0.0, 0.0, 0.0, 1.0]]
     */
    addNode(jsonIn) {
        if(jsonIn.nodeValue !== undefined && jsonIn.nodeValue !== null) {
            this.nodeValues.push(jsonIn.nodeValue);
            this.lastNodeValues.push(jsonIn.nodeValue);
        } else {
            this.nodeValues.push(0.0);
            this.lastNodeValues.push(0.0);
        }

        if(jsonIn.nodeValueB !== undefined && jsonIn.nodeValueB !== null) {
            this.nodeValuesB.push(jsonIn.nodeValueB);
            this.lastNodeValuesB.push(jsonIn.nodeValueB);
        } else {
            this.nodeValuesB.push(0.0);
            this.lastNodeValuesB.push(0.0);
        }

        if(jsonIn.nodeValueC !== undefined && jsonIn.nodeValueC !== null) {
            this.nodeValuesC.push(jsonIn.nodeValueC);
            this.lastNodeValuesC.push(jsonIn.nodeValueC);
        } else {
            this.nodeValuesC.push(0.0);
            this.lastNodeValuesC.push(0.0);
        }

        if(jsonIn.nodeValueD !== undefined && jsonIn.nodeValueD !== null) {
            this.nodeValuesD.push(jsonIn.nodeValueD);
            this.lastNodeValuesD.push(jsonIn.nodeValueD);
        } else {
            this.nodeValuesD.push(0.0);
            this.lastNodeValuesD.push(0.0);
        }

        if(jsonIn.nodeValueE !== undefined && jsonIn.nodeValueE !== null) {
            this.nodeValuesE.push(jsonIn.nodeValueE);
            this.lastNodeValuesE.push(jsonIn.nodeValueE);
        } else {
            this.nodeValuesE.push(0.0);
            this.lastNodeValuesE.push(0.0);
        }

        if(jsonIn.nodeValueF !== undefined && jsonIn.nodeValueF !== null) {
            this.nodeValuesF.push(jsonIn.nodeValueF);
            this.lastNodeValuesF.push(jsonIn.nodeValueF);
        } else {
            this.nodeValuesF.push(0.0);
            this.lastNodeValuesF.push(0.0);
        }

        this.nodeTypes.push(jsonIn.nodeType);

        this.graph.currentNeuron++;
        this.graph.afferentNodesCount++;

        let offs = 1000;
        let pos = [-(offs/2)+(Math.random()*offs), -(offs/2)+(Math.random()*offs), -(offs/2)+(Math.random()*offs), 1.0];
        let dest = (jsonIn.destination !== undefined && jsonIn.destination !== null) ? jsonIn.destination : [0.0, 0.0, 0.0, 1.0];
        let enableDest = (jsonIn.destination !== undefined && jsonIn.destination !== null) ? 1.0 : 0.0;

        this.graph.addNode({
            "name": jsonIn.name,
            "data": jsonIn.name,
            "label": jsonIn.name.toString(),
            "position": pos,
            "color": Resources.imgWhite(),
            "layoutNodeArgumentData": {
                "nodeColor": [1.0, 1.0, 1.0, 1.0],
                "enableDestination": enableDest,
                "dest": dest
            },
            "onmouseup": (nodeData) => {

            } });
    };

    /**
     * @param {Object} jsonIn
     * @param {String} jsonIn.origin
     * @param {String} jsonIn.target
     */
    addRelation(jsonIn) {
        this.graph.addLink({
            "origin": jsonIn.origin,
            "target": jsonIn.target,
            "directed": true,
            "showArrow": false});
    };

    tick() {
        let nArr = [];
        if(this.nodeValues.length > 0 || this.nodeValuesB.length > 0 || this.nodeValuesC.length > 0 || this.nodeValuesD.length > 0 || this.nodeValuesE.length > 0 || this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValues[n] = (this.nodeValues[n] !== undefined && this.nodeValues[n] !== null) ? this.nodeValues[n] : this.lastNodeValues[n];

            this.lastNodeValues = this.nodeValues;
            nArr = nArr.concat(this.nodeValues);
        }
        if(this.nodeValuesB.length > 0 || this.nodeValuesC.length > 0 || this.nodeValuesD.length > 0 || this.nodeValuesE.length > 0 || this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValuesB[n] = (this.nodeValuesB[n] !== undefined && this.nodeValuesB[n] !== null) ? this.nodeValuesB[n] : this.lastNodeValues[n];

            this.lastNodeValuesB = this.nodeValuesB;
            nArr = nArr.concat(this.nodeValuesB);
        }
        if(this.nodeValuesC.length > 0 || this.nodeValuesD.length > 0 || this.nodeValuesE.length > 0 || this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValuesC[n] = (this.nodeValuesC[n] !== undefined && this.nodeValuesC[n] !== null) ? this.nodeValuesC[n] : this.lastNodeValues[n];

            this.lastNodeValuesC = this.nodeValuesC;
            nArr = nArr.concat(this.nodeValuesC);
        }
        if(this.nodeValuesD.length > 0 || this.nodeValuesE.length > 0 || this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValuesD[n] = (this.nodeValuesD[n] !== undefined && this.nodeValuesD[n] !== null) ? this.nodeValuesD[n] : this.lastNodeValues[n];

            this.lastNodeValuesD = this.nodeValuesD;
            nArr = nArr.concat(this.nodeValuesD);
        }
        if(this.nodeValuesE.length > 0 || this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValuesE[n] = (this.nodeValuesE[n] !== undefined && this.nodeValuesE[n] !== null) ? this.nodeValuesE[n] : this.lastNodeValues[n];

            this.lastNodeValuesE = this.nodeValuesE;
            nArr = nArr.concat(this.nodeValuesE);
        }
        if(this.nodeValuesF.length > 0) {
            for(let n=0; n < this.nodeTypes.length; n++)
                this.nodeValuesF[n] = (this.nodeValuesF[n] !== undefined && this.nodeValuesF[n] !== null) ? this.nodeValuesF[n] : this.lastNodeValues[n];

            this.lastNodeValuesF = this.nodeValuesF;
            nArr = nArr.concat(this.nodeValuesF);
        }

        if( this.nodeValues.length > 0 ||
            this.nodeValuesB.length > 0 ||
            this.nodeValuesC.length > 0 ||
            this.nodeValuesD.length > 0 ||
            this.nodeValuesE.length > 0 ||
            this.nodeValuesF.length > 0) {
            nArr = nArr.concat(this.nodeTypes);

            this.graph.forward({"state": nArr, // A,B,C, A,B,C // value typeId
                "readOutput": false,
                "onAction": (maxacts) => {

                }});
            this.nodeValues = [];
            this.nodeValuesB = [];
            this.nodeValuesC = [];
            this.nodeValuesD = [];
            this.nodeValuesE = [];
            this.nodeValuesF = [];
        }


        if(this.sce.project !== null)
            this.sce.project.getActiveStage().tick();
    };

}
global.GRel = GRel;
module.exports.GRel = GRel;