/* ==================================================
* Author: Sebastien CATHALAN
* Web: www.apliko.fr
*
* This file is used to demonstrate an industry's
* implementation of the WebGL.
* It is JUST a demo and nothing else!
*
* -----> DO NOT use it in production <-----
*
* ================================================== */
"use strict";


var js3dDemoInstance;


function js3dDemo () {

js3dDemoInstance = this;



// Colours table
// We can have as many tables as we want, which contain an array of allowed colours
// colour object:
// hex : Hexadecimal colour value (eg: FFFFFF)
// pant : Pantone code name
// name : Literal English colour name
// cn : Chinese colour name
// code : Can be used to store any other data
this.colors = {};
this.colors.classic = [{"hex":"000000","code":"02","pant":"Pantone Black C","cn":"\u9ed1\u8272","name":"Black"},{"hex":"FFFFFF","code":"020","pant":"Pantone 000C","cn":"\u767d\u8272","name":"White"},{"hex":"F68121","code":"01","pant":"Pantone 138c","cn":"\u91d1\u9ec4\u8272","name":"Gold"},{"hex":"00612C","code":"03","pant":"Pantone 350c","cn":"\u58a8\u7eff\u8272","name":"Bottle Green"},{"hex":"990000","code":"04","pant":"Pantone 222c","cn":"\u9152\u7ea2\u8272","name":"Burgundy"},{"hex":"663300","code":"05","pant":"Pantone 439c","cn":"\u5de7\u514b\u529b\u8272","name":"Brown"},{"hex":"FFF4D6","code":"06","pant":"Pantone 7499c","cn":"\u7c73\u767d\u8272","name":"Cream"},{"hex":"2E8C40","code":"07","pant":"Pantone 362c","cn":"\u7fe0\u7eff\u8272","name":"Emerald Green"},{"hex":"6A757B","code":"08","pant":"Pantone 430c","cn":"\u6df1\u7070\u8272","name":"Grey"},{"hex":"FF00FF","code":"09","pant":"Pantone 227c","cn":"\u6df1\u6885\u7ea2","name":"Hot Pink"},{"hex":"008C7F","code":"010","pant":"Pantone 3295c","cn":"\u8349\u7eff\u8272","name":"Jade Green"},{"hex":"00CC33","code":"011","pant":"Pantone 361c","cn":"\u8367\u5149\u7eff","name":"Lime"},{"hex":"981934","code":"012","pant":"Pantone 208c","cn":"\u67a3\u7ea2\u8272","name":"Maroon"},{"hex":"000066","code":"013","pant":"Pantone 2767c","cn":"\u5b9d\u84dd\u8272","name":"Navy Blue"},{"hex":"F25822","code":"014","pant":"Pantone 021c","cn":"\u6a59\u8272","name":"Orange"},{"hex":"94C6E1","code":"015","pant":"Pantone 276c","cn":"\u7c89\u84dd\u8272","name":"Powder Blue"},{"hex":"712E75","code":"016","pant":"Pantone 259c","cn":"\u7d2b\u8272","name":"Purple"},{"hex":"ED1B24","code":"017","pant":"Pantone 193c","cn":"\u7ea2\u8272","name":"Red"},{"hex":"0F75BD","code":"018","pant":"Pantone 288c","cn":"\u5f69\u84dd\u8272","name":"Royal Blue"},{"hex":"56C9F5","code":"019","pant":"Pantone 284c","cn":"\u5929\u84dd\u8272","name":"Sky Blue"},{"hex":"FBCB05","code":"021","pant":"Pantone 136c","cn":"\u91d1\u9ec4\u8272","name":"Amber Yellow"},{"hex":"FEF200","code":"022","pant":"Pantone 115c","cn":"\u86cb\u9ec4\u8272","name":"Canary Yellow"},{"hex":"F8BFC6","code":"023","pant":"Pantone 495c","cn":"\u7c89\u7ea2\u8272","name":"Light Pink"},{"hex":"D1BEDE","code":"024","pant":"Pantone 514c","cn":"\u7c89\u7d2b\u8272","name":"Lilac"},{"hex":"00A0DD","code":"025","pant":"Pantone 312c","cn":"\u6e56\u84dd\u8272","name":"Cyan"},{"hex":"006633","code":"026","pant":"Pantone 349","cn":"WS \u6df1\u7fe0\u7effG1","name":"WS Emerald Green"},{"hex":"9933CC","code":"027","pant":"Pantone 266","cn":"WS \u6d45\u7d2b\u8272G1","name":"WS Purple"},{"hex":"F5EEB7","code":"","pant":"Pantone 7499","cn":"\u9ec4\u8910\u8272","name":"Khaki"},{"hex":"CCCCCC","code":"","pant":"Pantone 441","cn":"\u82b1\u7070\u8272","name":"Marl Grey"}];
this.colors.socks = [{"hex":"F68121","code":"C1935","pant":"","cn":"\u91d1\u9ec4\u8272","name":"Gold"},{"hex":"000000","code":"Black","pant":"","cn":"\u9ed1\u8272","name":"Black"},{"hex":"00612C","code":"E915","pant":"","cn":"\u58a8\u7eff\u8272","name":"Bottle Green"},{"hex":"990000","code":"F2111","pant":"","cn":"\u9152\u7ea2\u8272","name":"Burgundy"},{"hex":"663300","code":"Brown","pant":"","cn":"\u68d5\u8272","name":"Brown"},{"hex":"FFF4D6","code":"Cream","pant":"","cn":"\u7c73\u767d\u8272","name":"Cream"},{"hex":"2E8C40","code":"E1904","pant":"","cn":"\u7fe0\u7eff\u8272","name":"Emerald Green"},{"hex":"6A757B","code":"A1195","pant":"","cn":"\u6df1\u7070\u8272","name":"Grey"},{"hex":"FF00FF","code":"216","pant":"","cn":"\u6df1\u6885\u7ea2","name":"Hot Pink"},{"hex":"008C7F","code":"E66","pant":"","cn":"\u8349\u7eff\u8272","name":"Jade Green"},{"hex":"2E8C40","code":"E298","pant":"","cn":"\u8367\u5149\u7eff","name":"Lime"},{"hex":"981934","code":"E-2111","pant":"","cn":"\u67a3\u7ea2\u8272","name":"Maroon"},{"hex":"000066","code":"531","pant":"","cn":"\u5b9d\u84dd\u8272","name":"Navy Blue"},{"hex":"F25822","code":"840","pant":"","cn":"\u6a59\u8272","name":"Orange"},{"hex":"94C6E1","code":"J3924","pant":"","cn":"\u7c89\u84dd\u8272","name":"Powder Blue"},{"hex":"712E75","code":"2685U","pant":"","cn":"\u7d2b\u8272","name":"Purple"},{"hex":"ED1B24","code":"F499","pant":"","cn":"\u7ea2\u8272","name":"Red"},{"hex":"0F75BD","code":"J2594","pant":"","cn":"\u5f69\u84dd\u8272","name":"Royal Blue"},{"hex":"56C9F5","code":"J2045","pant":"","cn":"\u5929\u84dd\u8272","name":"Sky Blue"},{"hex":"FFFFFF","code":"White","pant":"","cn":"\u767d\u8272","name":"White"},{"hex":"FBCB05","code":"C1935C","pant":"","cn":"\u91d1\u9ec4\u8272","name":"Amber Yellow"},{"hex":"FEF200","code":"406","pant":"","cn":"\u86cb\u9ec4\u8272","name":"Canary Yellow"},{"hex":"F8BFC6","code":"F4891","pant":"","cn":"\u7c89\u7ea2\u8272","name":"Light Pink"},{"hex":"D1BEDE","code":"Lilac","pant":"","cn":"\u7c89\u7d2b\u8272","name":"Lilac"},{"hex":"00A0DD","code":"J-4502","pant":"","cn":"\u6e56\u84dd\u8272","name":"Cyan"}];
this.colors.embroidery = [{"hex":"CCCCCC","code":"3376","pant":"","cn":"\u6d45\u7070\u8272","name":"Light Grey"},{"hex":"2E8C40","code":"3204","pant":"","cn":"\u7fe0\u7eff\u8272","name":"Emerald Green"},{"hex":"6A757B","code":"3340","pant":"","cn":"\u6df1\u7070\u8272","name":"Grey"},{"hex":"FF00FF","code":"2241","pant":"","cn":"\u6df1\u6885\u7ea2","name":"Hot Pink "},{"hex":"FEF200","code":"2378","pant":"","cn":"\u86cb\u9ec4\u8272","name":"Canary Yellow"},{"hex":"FBCB05","code":"2716","pant":"","cn":"\u91d1\u9ec4\u8272","name":"Amber Yellow"},{"hex":"000066","code":"3647","pant":"","cn":"\u5b9d\u84dd\u8272","name":"Navy Blue"},{"hex":"981934","code":"2346","pant":"","cn":"\u67a3\u7ea2\u8272","name":"Maroon"},{"hex":"FFF4D6","code":"2351","pant":"","cn":"\u7c73\u767d\u8272","name":"Cream"},{"hex":"00612C","code":"3024","pant":"","cn":"\u58a8\u7eff\u8272","name":"Bottle Green"},{"hex":"712E75","code":"3827","pant":"","cn":"\u7d2b\u8272","name":"Purple"},{"hex":"F25822","code":"2451","pant":"","cn":"\u6a59\u8272","name":"Orange"},{"hex":"FFFFFF","code":"2168","pant":"","cn":"\u767d\u8272","name":"White"},{"hex":"000000","code":"2170","pant":"","cn":"\u9ed1\u8272","name":"Black"},{"hex":"ED1B24","code":"2296","pant":"","cn":"\u7ea2\u8272","name":"Red"},{"hex":"F68121","code":"2387","pant":"","cn":"\u91d1\u9ec4\u8272","name":"Gold"},{"hex":"000099","code":"3686","pant":"","cn":"\u6d45\u5f69\u84dd","name":"Light Royal Blue"},{"hex":"56C9F5","code":"3635","pant":"","cn":"\u5929\u84dd\u8272","name":"Sky Blue"},{"hex":"0F75BD","code":"3704","pant":"","cn":"\u5f69\u84dd\u8272","name":"Royal Blue"},{"hex":"663300","code":"2783","pant":"","cn":"\u5de7\u514b\u529b\u8272","name":"Brown "},{"hex":"F8BFC6","code":"2262","pant":"","cn":"\u7c89\u7ea2\u8272","name":"Light Pink"},{"hex":"00A0DD","code":"3591","pant":"","cn":"\u6e56\u84dd\u8272","name":"Cyan"}];



// Layers list with pre-setting
// - color : Property used to define the initial colour at start-up
// - fixed : true/false. If set to true, the layer is not editable and the file will stay untouched
// - coltable : Select the colours table. Eg: an embroidery layer don't have as many colours as a printed layer.
this.imgList = [];
this.imgList.push({img:null, fixed:false, coltable:'classic', color:'FFFFFF', pant:'Pantone 000C', src:'/public/js/project/js3d/textures/1024/layer1.png'});
this.imgList.push({img:null, fixed:false, coltable:'classic', color:'94C6E1', pant:'Pantone 276c', src:'/public/js/project/js3d/textures/1024/layer2.png'});
this.imgList.push({img:null, fixed:false, coltable:'classic', color:'000000', pant:'Pantone Black C', src:'/public/js/project/js3d/textures/1024/layer3.png'});
this.imgList.push({img:null, fixed:false, coltable:'classic', color:'ED1B24', pant:'Pantone 193c', src:'/public/js/project/js3d/textures/1024/layer4.png'});
this.imgList.push({img:null, fixed:true, src:'/public/js/project/js3d/textures/1024/fixed01.png'});



this.imgLoaded = false;
this.textureCanvas = null; // The canvas that will store the final texture (merged layers)




// ----------------------------------------------------------
// hexToRGB:
// ----------------------------------------------------------
// Return an object with the properties R, G and B in Integer
this.hexToRGB = function(hex) {
if (hex == '000000') hex = '292929'; // We don't want the darkest black

var long = parseInt(hex.replace(/^#/, ""), 16);
return {
R: (long >>> 16) & 0xff,
G: (long >>> 8) & 0xff,
B: long & 0xff
};
}




// ----------------------------------------------------------
// getOriginalPixels:
// ----------------------------------------------------------
// Return a canvas containing a copy of an original layer
this.getOriginalPixels = function(img)
{
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");

canvas.width = img.width;
canvas.height = img.height;

ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
return canvas;
}




// ----------------------------------------------------------
// applyLayer:
// ----------------------------------------------------------
// Colourize and merge a layer to the newly created texture
this.applyLayer = function(img, newcolor) {
var colorRGB = this.hexToRGB(newcolor+"");

var c = document.createElement('canvas');
c.width = img.width;
c.height = img.height;

var ctx = c.getContext('2d');
ctx.drawImage(img, 0, 0);


/*
// Slower solution : pixel by pixel
var imgData = ctx.getImageData(0, 0, c.width, c.height );

// Looping through all the pixels
for (var i=0; i < imgData.data.length; i += 4) {

// We don't colourize the transparent pixel (alpha=0)
// Colourizing them all will give the same result but it will hurt by a lot the performances
// FYI :
// A pixel has 4 Bytes
// BYTE#0 = Red
// BYTE#1 = Green
// BYTE#2 = Blue
// BYTE#3 = Alpha
if(imgData.data[i + 3] > 0) {
imgData.data[i] = colorRGB.R;
imgData.data[i + 1] = colorRGB.G;
imgData.data[i + 2] = colorRGB.B;

}
}
ctx.putImageData(imgData,0,0);
*/


// Faster solution : use Canvas 2D API function
ctx.globalCompositeOperation = 'source-in';
ctx.fillStyle = '#' + newcolor;
ctx.fillRect(0, 0, c.width, c.height);



this.textureCanvas.drawImg(c,0,0);
c.remove();
}



// ----------------------------------------------------------
// doLoadImage:
// ----------------------------------------------------------
// Loop through the array imgList to load the images one by one.
// When the images are all loaded, it calls drawTexture() to apply the texture to the 3D object.
this.doLoadImage = function() {
var imgFound = false;

// Load the images one by one
for(var x = 0; x < this.imgList.length; x++){
if (this.imgList[x]['img']==null) {
imgFound = true;
this.imgList[x]['img'] = new Image();
this.imgList[x]['img'].onload = function() { // Once an image is loaded we load the next one in the list
js3dDemoInstance.doLoadImage(); // Load the next image
}
this.imgList[x]['img'].src = this.imgList[x]['src'];
break;
}
}

// The images have all been loaded, we can apply the texture to the 3D object
if (!imgFound) {
this.imgLoaded = true;
this.drawTexture();
}
}



// ----------------------------------------------------------
// createColoursGrid:
// ----------------------------------------------------------
// Creates the colours selector UI and add it to the DOM
this.createColoursGrid = function() {

// Clean-up the DOM
$(".toolbox .partColors .subList").empty();

for(var x = 0; x < this.imgList.length; x++) {

// Some images are "FIXED", that mean they are not allowed to be colorized (eg: logo, decoration,...)
if (this.imgList[x]['fixed']==false) {

var col = $('<div class="colorbox"><div class="infocolor">'+this.imgList[x]['pant']+'</div></div>');
col.data("layer",this.imgList[x])
.css('background-color', '#'+this.imgList[x]['color'])
.on('click', function() {

// If the colour selector UI is already open for the same layer we don't create it
if ( $('#colorSelector').is(":visible") && ($('#colorSelector').data('selectedLayer') === this) ) {
$('#colorSelector').data('selectedLayer',null).hide();

// The colour selector is not open yet, we set it with the correct color list because each 3D object can use a different list
} else {
$('#colorSelector').data('selectedLayer', this);
// We take from the layer the colors list to be used
var colorTable = $(this).data('layer')['coltable'];

if ( $('#colorSelector').data('colorscheme') != colorTable ) { // Generate the colour selector UI
$('#colorSelector').data('colorscheme', colorTable);
$('#colorSelector .colorsList').empty();

for(var y = 0; y < js3dDemoInstance.colors[colorTable].length; y++) {
var colb = $('<div class="colorbox"></div>');
colb.data('color', js3dDemoInstance.colors[colorTable][y])
.css('background-color', '#'+js3dDemoInstance.colors[colorTable][y]['hex'])
.on('click', function() {
var selectedColor = $(this).data('color');
var selectedBoxLayer = $("#colorSelector").data('selectedLayer');

var selectedLayer = $(selectedBoxLayer).data('layer');
selectedLayer['color'] = selectedColor['hex'];

$(selectedBoxLayer).find('.infocolor').html(selectedColor['pant']);
$(selectedBoxLayer).css('background-color', '#'+selectedColor['hex']);

$("#colorSelector").hide();

js3dDemoInstance.drawTexture();
});

$('#colorSelector .colorsList').append(colb);
}
}

var pos = $(this).offset();
pos.top = pos.top + $(this).height() + 3;
pos.left = pos.left + $(this).width() - ($(this).width()/2);
$('#colorSelector').css({top: pos.top, left: pos.left}).show();
}
});

$(".toolbox .partColors .subList").append(col);

}
}
} // END createColoursGrid()



// ----------------------------------------------------------
// drawTexture:
// ----------------------------------------------------------
// Merge all the layers with the selected colours to create a texture suitable for the 3D object
this.drawTexture = function() {

// Makes sure that the layers are ready (fully loaded) before using them
if (this.imgLoaded && (this.textureCanvas!=null)) {
var context = this.textureCanvas.getContext('2d');
context.clearRect(0, 0, this.textureCanvas.width, this.textureCanvas.height);

// Go through all the layers
for(var x = 0; x < this.imgList.length; x++) {

// if it's a fixed layer we merge as is
if (this.imgList[x]['fixed']) {
this.textureCanvas.drawImg(this.imgList[x]['img']);

// The normal layer as to be colorized
} else {
this.applyLayer(this.imgList[x]['img'], this.imgList[x]['color']);
}
}

}
}




// ----------------------------------------------------------
// Constructor
// 1. Initialise the 3D engine
// 2. Load the 3D objects
// 3. Load the Layers images
// ----------------------------------------------------------
if (BABYLON.Engine.isSupported()) {


// Load the layers
this.doLoadImage();

// Add the buttons to the DOM (the buttons to change the layer's colour)
this.createColoursGrid();


// Babylon Initialisation
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);


// Add a function to draw the texture
BABYLON.DynamicTexture.prototype.drawImg = function (img) {
var size = this.getSize();
this._context.drawImage(img, 0, 0);
this.update(true);
};


// Request Babylon to load the 3D scene containing our 3D object as a json file
BABYLON.SceneLoader.Load("", "../public/js/project/js3d/rugby_shirt_blank1.babylon.json", engine, function (newScene) {

// Wait for textures and shaders to be ready
newScene.executeWhenReady(function () {

// Set the backside (the inside of our object to also display the texture)
newScene.materials.forEach(function(entry) {
entry.backFaceCulling = false;
});

console.log(newScene);


// The texture will be easily accessible with the "textureCanvas" variable
js3dDemoInstance.textureCanvas = new BABYLON.DynamicTexture("dynamictexture", 1024, newScene, true);


// Go through all the object in the scene to attach the texture
// and set some setting to control the surface of our texture (eg: the way the light will interact with the texture)
newScene.meshes.forEach(function(entry) {
entry.material.diffuseTexture = js3dDemoInstance.textureCanvas;
entry.material.specularColor = {r:0.1, b:0.1, g:0.1};
entry.material.diffuseColor = {r:1, b:1, g:1};
entry.material.backFaceCulling = false;
entry.material.diffuseTexture.hasAlpha = true;
});

js3dDemoInstance.drawTexture();

// Create a Rotating camera (that will turn around a pivot point)
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 1.5, 7, new BABYLON.Vector3(0, 0, 0), newScene);
camera.wheelPrecision = 20;

// Define the camera as the active (as if we were seeing through it)
newScene.activeCamera = camera;

// Attach the mouse and keyboard to the camera
newScene.activeCamera.attachControl(canvas, false);

// Create a hemispheric light
var light = new BABYLON.HemisphericLight("Omni0", new BABYLON.Vector3(0, 1, 0), newScene);

// Transparent scene background
// newScene.autoClear = false;
//newScene.clearColor = new BABYLON.Color3(250, 248, 245);
newScene.clearColor = new BABYLON.Color4(0,0,0,0.0000000000000001);





// Everything has been set up correctly.
// Makes Babylon loop to continuously render the scene
engine.runRenderLoop(function() {
newScene.render();
});
});


// Loading progression event
}, function (progress) {
// Add a visual feedback about the loading
});


} // END - Constructor


}