// const APPL = 1, COMP = 2, BU = 3, ORG = 4, AGGR = 5; GROUP = 6;
// const QUEUE = 100, TOPIC = 101, FILE = 102, DB = 103, OTHER = 104;
// const PRODUCER = 1, CONSUMER = 2, PUBLISHER = 3, SUBSCRIBER = 4, CONNECTED = 5, SOURCE= 6, SINK= 7, SOURCESINK = 8, SERVICE = 1000;

function createNodeMesh(node, isBillBoard, isAnchor, isExternal) {
	//alert("Node kind " + node.Kind); 
	switch(node.Kind) {
		case APPL:
			if (isBillBoard) {
				aObj = BABYLON.MeshBuilder.CreatePlane(node.Name, { width: 8, height: 5, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene); 
				aObj.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
				if (isExternal) showArchiApp(aObj, scene, backColorAppsExt, foreColor); else showArchiApp(aObj, scene, backColorApps, foreColor);
			} else {
				aObj = BABYLON.Mesh.CreateSphere(node.Name, 6, 2, scene);
				if (isExternal) aObj.material = _materialExt; else aObj.material = _material1;
			}
			break;
		case COMP:
			aObj = BABYLON.Mesh.CreateBox(node.Name, 7.0, scene, false, BABYLON.Mesh.DOUBLESIDE );
			if (isExternal) showArchiApp(aObj, scene, backColorAppsExt, foreColor); else showArchiApp(aObj, scene, backColorApps, foreColor);
			aObj.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
			break;
		case BU:
			aObj = createPictureMesh(node.Name, 7, _materialBU);
			break;
		case ORG:
			aObj = createPictureMesh(node.Name, 8, _materialOrg);
			break;
		case GROUP:
			aObj = createPictureMesh2(node.Name, 7, 6, _materialGroup, isExternal);
			break;
		case FILE:
			aObj = createPictureMesh(node.Name, 6, _materialFile);
			break;
		case QUEUE:
		case TOPIC:
			for (var key in node.Params) {
				var entry;
				var start;
				var end;
				if (node.Params.hasOwnProperty(key)) {
					entry = node.Params[key];
					//alert("Entry " + entry.DES); 
					if (entry.DES == "in") {
						start = new BABYLON.Vector3(entry.X, entry.Y, entry.Z);
						//alert("start: " + entry.X + " " + entry.Y + " " + entry.Z);
					} else {
						end = new BABYLON.Vector3(entry.X, entry.Y, entry.Z);
						//alert("end: " + entry.X + " " + entry.Y + " " + entry.Z);
					}
				}
			}
			if (node.Kind == QUEUE)
				aObj = createQueueMesh(node.Name, start, end, 2.5, 4, _material2);
			else
				aObj = createTopicMesh(node.Name, start, end, 1.1, 4, _material2);
			break;
		case DB:
			aObj = createDbMesh (node.Name);
			break;
		default:
			aObj = createPictureMesh(node.Name, 5, _materialOtherC);				
	}                
	aObj._type = "N";
	aObj._subtype = node.Kind;
	return aObj;
}	
// This does not work
function createGroupMesh (name, width, height) {
	var toMerge = [];
	for (i=0; i < 3; i++) {
		var c = i*0.3;
		var pos = new BABYLON.Vector3(c, c, c);
		var mesh = BABYLON.MeshBuilder.CreatePlane(name, { width: width, height: height, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene); 
		mesh.position = pos;
		mesh.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
		if (i == 2) showArchiApp(mesh, scene, backColorAppsExt, foreColor); else mesh.material = _material1;
		toMerge.push(mesh);
	}
	var newMesh = BABYLON.Mesh.MergeMeshes(toMerge, true, true, null, false, false);
	newMesh.name = name;
	newMesh.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
	return newMesh;
}

function createDbMesh (name) {
	// Colors per surface
    cT = new BABYLON.Color4(0.3, 0.5, 1.0, 1),		// bottom cap
    c1 = new BABYLON.Color4(0.2, 0.5, 1.0, 1),				// tube
    c2 = new BABYLON.Color4(0.5, 0.5, 1.0, 1),				// tube
    cB = new BABYLON.Color4(0.5, 0.5, 1.0, 1)		// top cap
	var colors = [  cT, c1, c2, c1, c2, cB];
	var cylinder = BABYLON.MeshBuilder.CreateCylinder(name, { height: 3, diameter: 6, subdivisions: 4, hasRings: true, faceColors: colors, updatable: true}, scene);
	return cylinder;
 }
 
function createPictureMesh(name, size, material) {
    var ou = BABYLON.Mesh.CreatePlane(name, size, scene);
    ou.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
    ou.material = material;
	return ou;
}

function createPictureMesh2(name, width, height, material, isExternal) {
	ou = BABYLON.Mesh.CreateBox(name, height, scene, false, BABYLON.Mesh.DOUBLESIDE );
	if (isExternal) showArchiApp(ou, scene, backColorAppsExt, foreColor); else showArchiApp(ou, scene, backColorApps, foreColor);
    var plane = BABYLON.Mesh.CreatePlane(name, width * 2.5 , scene);
	material.alpha = 0.5;
    plane.material = material;
    plane.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
	plane.parent = ou;
	return ou;
}

function createQueueMesh(name, start, end, rad, count, mat)
{
	var s = start;
	var e = end;
	var factor1 = 0.8;
	var factor2 = 0.5;
	var gg = factor1/count;
	var gg2 = gg/(factor2*(count-1)); //gg/(0.5*(count-1));
	var inc = (start.subtract(end)).multiplyByFloats(gg,gg,gg);
	var step = inc.multiplyByFloats(gg2,gg2,gg2);
	//alert("inc " + inc + "step " + step);
	var toMerge = [];
	for (let i = 0; i < count; i++) {
		e = s.subtract(inc).add(step);
		var d1 = BABYLON.Vector3.Distance(s,start);
		var d2 = BABYLON.Vector3.Distance(e,end);
		var dd = BABYLON.Vector3.Distance(s,e);
		var cap = BABYLON.Mesh.CAP_ALL;
		//alert("index>> " + index + " s-start>> " + d1 + " e-end>> " + d2 + " <>" + dd);
		tube = BABYLON.MeshBuilder.CreateTube("tube", {path: [ s, e], radius: rad, sideOrientation: BABYLON.Mesh.DOUBLESIDE, cap: cap}, scene);
		tube.material = mat;
		s = e.subtract(step);
		toMerge.push(tube);
	}
	var newMesh = BABYLON.Mesh.MergeMeshes(toMerge, true, true, null, false, false);
	newMesh.name = name;
	return newMesh;
}

function createTopicMesh(name, start, end, rad, count, mat)
{
	var cap;
	var s = start;
	var e = end;
	var factor1 = 0.6;
	var factor2 = 1.2;
	var gg = factor1/count;
	var gg2 = gg*factor2/(factor1*(count-1));
	var inc = (start.subtract(end)).multiplyByFloats(gg,gg,gg);
	var step = inc.multiplyByFloats(gg2,gg2,gg2);
	//alert("inc " + inc + "step " + step);
	var toMerge = [];
	for (let i = 0; i < count; i++) {
		//alert(i);
		var rr = rad * (count + i*2)/count;
		e = s.subtract(inc).add(step);
		var d1 = BABYLON.Vector3.Distance(s,start);
		var d2 = BABYLON.Vector3.Distance(e,end);
		var dd = BABYLON.Vector3.Distance(s,e);
		if (i == (count-1)) cap = BABYLON.Mesh.CAP_START; else cap = BABYLON.Mesh.CAP_ALL; // NO_CAP, CAP_START, CAP_END, CAP_ALL
		tube = BABYLON.MeshBuilder.CreateTube("tube", {path: [s, e], radius: rr, sideOrientation: BABYLON.Mesh.DOUBLESIDE, cap: cap}, scene);
		tube.material = mat;
		s = e.subtract(step);
		toMerge.push(tube);
	}
	var newMesh = BABYLON.Mesh.MergeMeshes(toMerge, true, true, null, false, false);
	newMesh.name = name;
	return newMesh;
}
	
function cloneApplMesh(name, appMesh, isBillBoard, isExternal) {
	aObj = appMesh.clone(name);
	aObj._type = appMesh._type;
	aObj._subtype = appMesh._subtype;
	if (isBillBoard) {
		if (isExternal) showArchiApp(aObj, scene, backColorAppsExt, foreColor); else showArchiApp(aObj, scene, backColorApps, foreColor);
	}
	return aObj;
}

function createSubnodeMesh(subnode, svcBillBoard, svcLargeBlue, isExternal, isSpecial) {
	if (svcBillBoard) {
		sObj = BABYLON.MeshBuilder.CreatePlane(subnode.Name, { width: 8, height: 5, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene);
	} else {
		if (svcLargeBlue) {
			sObj = BABYLON.Mesh.CreateSphere(subnode.Name, 8, 3, scene);
			sObj.material = _material2;
		} else {
			if (isSpecial) {
				sObj = BABYLON.Mesh.CreateSphere(subnode.Name, 6, 1.2, scene);
				sObj.material = _material3;
			} else {
				sObj = BABYLON.Mesh.CreateSphere(subnode.Name, 6, 2, scene);
				sObj.material = _material2;
			}
		}
	}
	return sObj;
}

function createHelpers() {
    for (var key in model.Helpers) {
        if (model.Helpers.hasOwnProperty(key)) {
            helper1 = BABYLON.Mesh.CreateBox("helper1", model.Helpers[key].W * 2.0, scene);
            var pos1 = new BABYLON.Vector3(model.Helpers[key].X, model.Helpers[key].Y, model.Helpers[key].Z);
            var pos2 = new BABYLON.Vector3(model.Helpers[key].X, model.Helpers[key].H, model.Helpers[key].Z);
            //alert(" Helpers y:" + model.Helpers[key].Y + " h:" + model.Helpers[key].H);

            var mat = new BABYLON.StandardMaterial("mat", scene);
            if (CONFIG.planesVisible) mat.alpha = 0.2; else mat.alpha = 0.0;

            helper1.material = mat;
            helper1.scaling.y = 0.001;
            helper1.position = pos1;
            helper2 = helper1.createInstance("helper2");
            helper2.position = pos2;
            //camera.position = new BABYLON.Vector3(box1.position.x, (box1.position.y + box2.position.y) / 2.0, box1.position.z * 0.2); //box1.position.z); // * (-0.5)
        }
    }
}
