import { Object3D, Vector3, BoxBufferGeometry, Color, Mesh, MeshBasicMaterial, PerspectiveCamera, OrthographicCamera,
Scene, WebGLRenderer, AmbientLight, DirectionalLight, HemisphereLight, MeshStandardMaterial,
AxesHelper, GridHelper, Matrix4, SphereBufferGeometry, CylinderBufferGeometry, ConeGeometry, Group, LoadingManager, MeshPhysicalMaterial, Vector2, FrontSide,
	BackSide, DoubleSide, PMREMGenerator, TextureLoader, PointLight, UVMapping, CubeReflectionMapping, CubeRefractionMapping,
	EquirectangularReflectionMapping, EquirectangularRefractionMapping, CubeUVReflectionMapping,
	CubeUVRefractionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping,
	NearestFilter, LinearFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapNearestFilter,
	LinearMipmapLinearFilter, BufferGeometry, Float32BufferAttribute, PointsMaterial, Points, ArrowHelper, TextGeometry, CubeTextureLoader,sRGBEncoding
} from 'https://cdn.skypack.dev/three@0.135.0/build/three.module.js';
import { OrbitControls } from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/controls/OrbitControls.js';
import {OBJLoader} from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/loaders/OBJLoader.js';
import {STLLoader} from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/loaders/STLLoader.js';
import {ColladaLoader} from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/loaders/ColladaLoader.js';
import {GUI} from 'https://cdn.skypack.dev/dat.gui';
import {ParametricGeometry} from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/geometries/ParametricGeometry.js'


//0.126.1 0.137.5
import { RoomEnvironment } from 'https://unpkg.com/three@0.126.1/examples/jsm/environments/RoomEnvironment.js';

//--------------------SIMULATION ELEMENTS---------------------

//SIMULATION PARAMETERS GO HERE

function elapsedMs()
{
	return (new Date()).getTime();
}


class Objsim{
	constructor(_frames){
		this.frames = _frames;
		this.currentFrame = 0;
		this.shape = "I HAVE NO SHAPE YET";
	}

	hasLoaded()
	{
		return true;
	}

	nextFrame(){
		while( (this.currentFrame < this.frames.length-1) && ( 1000 * this.frames[this.currentFrame+1][0] + delay < (elapsedMs() - startMs)) )
		{
			this.currentFrame += 1;
		}
	}
	setFrameTime(time)
	{
		this.currentFrame = 0;
		while( (this.currentFrame < this.frames.length-1) && ( this.frames[this.currentFrame+1][0] < time) )
		{
			this.currentFrame += 1;
		}
	}
	showFrame(){
		this.shape.matrix.set( this.frames[this.currentFrame][ 1],this.frames[this.currentFrame][ 2],this.frames[this.currentFrame][ 3],this.frames[this.currentFrame][ 4],
							   this.frames[this.currentFrame][ 5],this.frames[this.currentFrame][ 6],this.frames[this.currentFrame][ 7],this.frames[this.currentFrame][ 8],
							   this.frames[this.currentFrame][ 9],this.frames[this.currentFrame][10],this.frames[this.currentFrame][11],this.frames[this.currentFrame][12],
							   this.frames[this.currentFrame][13],this.frames[this.currentFrame][14],this.frames[this.currentFrame][15],this.frames[this.currentFrame][16]);


	}
	setEnvMap(envMap)
	{
		this.shape.material.envMap = envMap;
		this.shape.material.needsUpdate = true;
	}
}

class Box extends Objsim{
	constructor(_width, _height, _depth, _frames, _material){
		super(_frames);
		this.width = _width;
		this.height = _height;
		this.depth = _depth;
		const geometry = new BoxBufferGeometry( this.width, this.height, this.depth);
		const cube = new Mesh( geometry, _material );
		cube.matrixAutoUpdate = false;
		this.shape = cube;
	}
}

class Ball extends Objsim{
	constructor(_radius, _frames, _material){
		super(_frames);
		this.radius = _radius;
		const geometry = new SphereBufferGeometry( this.radius, 64, 32);
		const sphere = new Mesh( geometry, _material);
		sphere.matrixAutoUpdate = false;
		this.shape = sphere;
	}
}

class Cylinder extends Objsim{
	constructor(_radius, _height, _frames, _material){
		super(_frames);
		this.radius = _radius;
		this.height = _height;
		const geometry = new CylinderBufferGeometry( this.radius, this.radius, this.height, 20 );
		const cylinder = new Mesh( geometry, _material);
		cylinder.matrixAutoUpdate = false;
		this.shape = cylinder;
	}
}

class Cone extends Objsim{
	constructor(_radius, _height, _frames, _material){
		super(_frames);
		this.radius = _radius;
		this.height = _height;
		const geometry = new ConeGeometry( this.radius, this.height, 20, 5, false, 0.0, 6.28 );
		const cone = new Mesh( geometry, _material);
		cone.matrixAutoUpdate = false;
		this.shape = cone;
	}
}

function signFun(x,n){
	return Math.sign(x)*( Math.pow(Math.abs(x),n))
}

class SmoothBox extends Objsim{



	constructor(_width, _height, _depth, _frames, _material){
		super(_frames);
		this.width = _width;
		this.height = _height;
		this.depth = _depth;

		const geometry = new ParametricGeometry( function fun(u,v,target) {
			let cosu = signFun(Math.cos(0.0001*Math.PI + 0.9999*Math.PI*u),0.5)
			let sinu = signFun(Math.sin(0.0001*Math.PI + 0.9999*Math.PI*u),0.5)
			let cosv = signFun(Math.cos(2*Math.PI*v),0.5)
			let sinv = signFun(Math.sin(2*Math.PI*v),0.5)

			let x = (_width/2)*sinu*cosv;
			let y = (_height/2)*sinu*sinv;
			let z = (_depth/2)*cosu;

	    	target.set( x, y, z );

		}, 25, 25 );


		const smoothCube = new Mesh( geometry, _material );
		smoothCube.matrixAutoUpdate = false;
		this.shape = smoothCube;
	}



}

class PointCloud extends Objsim{

	constructor(_points, _frames, _color, _size) {
		super(_frames);

		this.color = _color;
		this.points = _points
		this.size = _size;

		const vertices = []
		const geometry = new BufferGeometry();
		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
		const material = new PointsMaterial({color: this.color, size: this.size});
		this.shape  = new Points(geometry, material);
	}

	showFrame(){
		const vertices = [];

		for (let i = this.frames[this.currentFrame][1]; i < this.frames[this.currentFrame][2]; i++) {
			vertices.push(this.points[0][i], this.points[1][i], this.points[2][i]);
		}

		this.shape.geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));

	}

	setEnvMap(envMap) {}

}

class RigidObject extends Objsim
{

	constructor(_frames, _list_3dobject) {
		super(_frames);

		this.shape = new Group();
		this.shape.matrixAutoUpdate = false;

		const manager = new LoadingManager();

		let loader;

		for (let i = 0; i < _list_3dobject.length; i++) {
			const _3dobject = _list_3dobject[i];
			if (_3dobject.type === 'obj') {
				loader = new OBJLoader(manager);
				loader.load(_3dobject.url, (root) => {

					root.scale.set(_3dobject.scale, _3dobject.scale, _3dobject.scale);
					root.applyMatrix4(_3dobject.matrix)

					root.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = _3dobject.mesh_material;
						}
					});

					this.shape.add(root);
				});
			}
			if (_3dobject.type === 'stl') {
				loader = new STLLoader(manager);
				loader.load(_3dobject.url, (root) => {
					const mesh = new Mesh(root);

					mesh.scale.set(_3dobject.scale, _3dobject.scale, _3dobject.scale);
					mesh.applyMatrix4(_3dobject.matrix)

					mesh.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = _3dobject.mesh_material;
						}
					});

					this.shape.add(mesh);
				});
			}
			if (_3dobject.type === 'dae') {
				loader = new ColladaLoader(manager);
				loader.load(_3dobject.url, (root) => {
					const group = root.scene;

					group.scale.set(_3dobject.scale, _3dobject.scale, _3dobject.scale);
					group.applyMatrix4(_3dobject.matrix)

					group.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = _3dobject.mesh_material;
						}
					});

					this.shape.add(group);
				});
			}
		}

	}

	setEnvMapTemp(variable, envMap)
	{
		if(variable instanceof Mesh)
		{
			variable.material.envMap = envMap;
			variable.material.needsUpdate  = true;
		}
		else if (variable instanceof Group)
		{
			for(let i=0; i < variable.children.length; i++)
			{
				this.setEnvMapTemp(variable.children[i]);
			}
		}
	}
	setEnvMap(envMap) {
		this.setEnvMapTemp(this.shape, envMap);
	}

}

class Vector extends Objsim {


	constructor(_frames, _color, _thickness, _origin, _dir, _length) {
		super(_frames);

		this.color = _color;
		this.thickness = _thickness
		this.origin = new Vector3(_origin[0], _origin[1], _origin[2]);
		this.dir =  new Vector3(_dir[0], _dir[1], _dir[2]);
		this._length = length

		this.shape = new ArrowHelper( this.dir, this.origin, this.length, this.color );
		this.shape.line.material.linewidth = this.thickness;

	}

	showFrame() {
		this.shape.setLength(this.frames[this.currentFrame][3]);
		const dir = this.frames[this.currentFrame][2];
		const origin = this.frames[this.currentFrame][1];

		this.shape.setDirection(new Vector3(dir[0], dir[1], dir[2]));
		this.shape.position.set(origin[0], origin[1], origin[2]);
	}
	setEnvMap(envMap) {}
}

class PointLightSim extends Objsim {


	constructor(_frames) {
		super(_frames);
		this.shape = new PointLight(this.frames[0][1],this.frames[0][2],this.frames[0][3]);
		this.shape.position.set(this.frames[0][4][0],this.frames[0][4][1],this.frames[0][4][2]);
	}

	showFrame() {
		this.shape.color.set(this.frames[this.currentFrame][1]);
		this.shape.intensity = this.frames[this.currentFrame][2];
		this.shape.distance = this.frames[this.currentFrame][3];
		this.shape.position.set(this.frames[this.currentFrame][4][0],this.frames[this.currentFrame][4][1],this.frames[this.currentFrame][4][2]);
	}
	setEnvMap(envMap) {}
}

class HTMLDiv extends Objsim{

	constructor(_id, _frames){
		super(_frames);
		this.id = _id;
		this.shape = undefined;
	}

	showFrame() {
		var element = document.getElementById(this.id);

		element.innerHTML = this.frames[this.currentFrame][1];
		element.style.position = "absolute";
		element.style = this.frames[this.currentFrame][2];
	}
	setEnvMap(envMap) {}
}

class Robot extends Objsim{

	constructor(_objBase, _link, _frames, _htm_base_0, _htm_n_eef, _eef_frame_visible){
		super(_frames);

		this.loadedObjs = 0
		this.links = _link;

		this.totalNumberOfObjects = _objBase.length;

		for(let i=0; i<this.links.length; i++)
		{
			this.totalNumberOfObjects+= this.links[i].model3d.length;
		}

		this.htm_base_0 = _htm_base_0;

		//Function that creates a generic robot
		const base = new Group();
		base.name = "base";

		const baseFrame = new Group();
		baseFrame.name = "baseFrame";
		baseFrame.applyMatrix4(this.htm_base_0);


		//Create link groups
		let linkGroupList = [];

		for (let i = 0; i <= this.links.length; i++) {

			var linkGroup = new Group();
			linkGroup.name = "linkFrame" + i.toString();
			linkGroupList.push(linkGroup);

			linkGroup = new Group();
			linkGroup.name = "link" + i.toString();
			var axesHelper = new AxesHelper(0.2);
			axesHelper.matrixAutoUpdate = false;
			axesHelper.visible = true;
			linkGroup.add(axesHelper)

			if (i < this.links.length) {
				linkGroup.rotateZ(this.links[i].theta);
				linkGroup.translateZ(this.links[i].d);
				linkGroup.rotateX(this.links[i].alpha);
				linkGroup.translateX(this.links[i].a);
			}


			linkGroup.updateMatrix();

			linkGroupList.push(linkGroup);
		}

		var linkGroup = new Group();
		linkGroup.name = "eefFrame";
		linkGroupList.push(linkGroup);

		linkGroup = new Group();
		linkGroup.name = "eef";
		var axesHelper = new AxesHelper(0.2);
		axesHelper.matrixAutoUpdate = false;
		axesHelper.visible = _eef_frame_visible;
		linkGroup.add(axesHelper);
		linkGroup.applyMatrix4(_htm_n_eef)
		linkGroup.updateMatrix();
		linkGroupList.push(linkGroup);


		base.add(baseFrame)
		baseFrame.add(linkGroupList[0])

		for (let i = 0; i < linkGroupList.length-1; i++) {
			linkGroupList[i].add(linkGroupList[i + 1])
		}

		//Load 3D models

		this.shape = base;
		this.shape.matrixAutoUpdate = false;

		this.loadObj(_objBase,"base", "base", false)
		for (let i = 0; i < this.links.length-1; i++) {
			this.loadObj(this.links[i].model3d,"link" + (i+1).toString(), "link" + (i).toString(), this.links[i].showFrame)
		}
		this.loadObj(this.links[this.links.length-1].model3d,"link" + (this.links.length).toString(), "link" + (this.links.length).toString(), false)

		this.delta_config = []

		for (let i = 0; i < this.links.length; i++) {
			if(this.links[i].jointType == 0)
			{
				this.delta_config.push(this.shape.getObjectByName("link" + (i).toString()).rotation.z)
			}
			if(this.links[i].jointType == 1)
			{
				this.delta_config.push(this.shape.getObjectByName("link" + (i).toString()).position.z)

			}
		}

	}

	loadObj(obj, name1, name2, axisVisible) {

		const manager = new LoadingManager();
		const objLoader = new OBJLoader(manager);
		const stlLoader = new STLLoader(manager);
		const colladaLoader = new ColladaLoader(manager);

		for (let i = 0; i < obj.length; i++) {


			if (obj[i].type == "obj") {
				objLoader.load(obj[i].url, (root) => {
					root.scale.set(obj[i].scale, obj[i].scale, obj[i].scale);
					root.applyMatrix4(obj[i].matrix)

					root.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = obj[i].mesh_material;
						}
					});

					this.shape.getObjectByName(name2).add(root);
					this.loadedObjs += 1
				});
			}
			if (obj[i].type == "stl") {
				stlLoader.load(obj[i].url, (root) => {
					const mesh = new Mesh(root);
					mesh.scale.set(obj[i].scale, obj[i].scale, obj[i].scale);
					mesh.applyMatrix4(obj[i].matrix)

					mesh.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = obj[i].mesh_material;
						}
					});

					this.shape.getObjectByName(name2).add(mesh);
					this.loadedObjs += 1
				});
			}
			if (obj[i].type == "dae") {
				colladaLoader.load(obj[i].url, (root) => {
					const group = root.scene;
					group.scale.set(obj[i].scale, obj[i].scale, obj[i].scale);
					group.applyMatrix4(obj[i].matrix)

					group.traverse(function (child) {
						if (child instanceof Mesh) {
							child.material = obj[i].mesh_material;
						}
					});

					this.shape.getObjectByName(name2).add(group);
					this.loadedObjs += 1
				});
			}

		}

		this.shape.getObjectByName(name1).getObjectByProperty("type", "AxesHelper").visible = axisVisible;
	}

	hasLoaded()
	{
		return this.loadedObjs == this.totalNumberOfObjects;
	}

	//Function that updates frames
	showFrame(){
		//setting robot position
		this.shape.matrix.set( this.frames[this.currentFrame][ 1],this.frames[this.currentFrame][ 2],this.frames[this.currentFrame][ 3],this.frames[this.currentFrame][ 4],
							   this.frames[this.currentFrame][ 5],this.frames[this.currentFrame][ 6],this.frames[this.currentFrame][ 7],this.frames[this.currentFrame][ 8],
							   this.frames[this.currentFrame][ 9],this.frames[this.currentFrame][10],this.frames[this.currentFrame][11],this.frames[this.currentFrame][12],
							   this.frames[this.currentFrame][13],this.frames[this.currentFrame][14],this.frames[this.currentFrame][15],this.frames[this.currentFrame][16]);
		//setting robot configuration

		if(this.frames[this.currentFrame][17] != undefined){

			for(let i = 0; i < this.links.length; i++){
				const linkName = "linkFrame" + (i).toString();

				if(this.links[i].jointType == 0){
					this.shape.getObjectByName(linkName).rotation.z = this.frames[this.currentFrame][17][i] + this.delta_config[i];
				}else if (this.links[i].jointType == 1){
					this.shape.getObjectByName(linkName).position.z = this.frames[this.currentFrame][17][i] + this.delta_config[i];
				}

			}
		}
	}

	setEnvMapTemp(variable, envMap)
	{
		if(variable instanceof Mesh)
		{
			variable.material.envMap = envMap;
			variable.material.needsUpdate  = true;
		}
		else if (variable instanceof Group)
		{
			for(let i=0; i < variable.children.length; i++)
			{
				this.setEnvMapTemp(variable.children[i]);
			}
		}
	}
	setEnvMap(envMap) {
		this.setEnvMapTemp(this.shape, envMap);
	}
}

//------------------------------------------------------------

//--------------- BASIC ELEMENTS OF ANY SCENE ----------------

Object3D.DefaultUp = new Vector3(0,0,1); //Pointing Z axis up
const canvas = document.getElementById('scene_'+sceneID);// Selecting canvas

const scene = new Scene();//Instantiate the Scene
scene.background = new Color(backgroundColor);//Set background color

let camera;

if (cameraType == "perspective") {
	camera = new PerspectiveCamera(60, canvas.clientWidth / canvas.clientHeight, 0.1, 100);//Instantiate a camera
}
if (cameraType == "orthographic") {
	camera = new OrthographicCamera(-3.2, 3.2, 2.4, -2.4, 0.01, 100);
}



var ambientLight = new HemisphereLight('white','darkslategrey', 3);//Instantiate Ambient light
ambientLight.intensity = ambientLightIntensity;
scene.add(ambientLight);

const controls = new OrbitControls(camera, canvas);	//Instantiate orbit controls
controls.target.set(0, 0, 0);//Point camera at the origin

camera.position.set(cameraStartPose[0], cameraStartPose[1], cameraStartPose[2]);
//camera.rotation.set(cameraStartPose[3], cameraStartPose[4], cameraStartPose[5]);
camera.lookAt(new Vector3(cameraStartPose[3], cameraStartPose[4], cameraStartPose[5]));
camera.zoom = cameraStartPose[6];
camera.updateProjectionMatrix();

controls.target.set(0, 0, 0);//Point camera at the origin

const renderer = new WebGLRenderer({canvas, antialias: true});//Instantiate renderer
renderer.physicallyCorrectLights = true;//Enable physically Correct Lights
renderer.setSize(canvas.clientWidth, canvas.clientHeight);//Set render size
renderer.setPixelRatio(window.devicePixelRatio);//Set pixel ratio

let sceneElements = [];

if (showWorldFrame) {
	const axesHelper = new AxesHelper(0.5);
	axesHelper.renderOrder = 1;
	scene.add(axesHelper);
}

if (showGrid) {
	const gridHelper = new GridHelper(gridSize, gridDivisions);
	scene.add(gridHelper);
	gridHelper.rotation.x = 3.14 / 2;
}



//------------------------------------------------------------

//--------------- ADDING ELEMENTS TO THIS SCENE ---------------
//USER INPUT GOES HERE



// add stuff to the scene
for (let i = 0; i < sceneElements.length; i++) {
	if (typeof sceneElements[i].shape != "undefined") {
		scene.add(sceneElements[i].shape);
	}
}



//Add LDR to the scene
if ( !(ldrUrls.length==0) )
{
	const pmremGenerator = new PMREMGenerator( renderer );
	var ldrCubeMap = new CubeTextureLoader().load(ldrUrls, function () {

		var ldrCubeRenderTarget = pmremGenerator.fromCubemap(ldrCubeMap);

		ldrCubeMap.encoding = sRGBEncoding;


		for (let i = 0; i < sceneElements.length; i++) {
			sceneElements[i].setEnvMap(ldrCubeRenderTarget.texture);
		}
		scene.background = ldrCubeMap;
	});
	renderer.toneMappingExposure = 1.0;
}



//Add gui
var gui = new GUI({autoPlace: false, width: "800px"});
var customContainer = document.getElementById('canvas_container_'+sceneID);
customContainer.appendChild(gui.domElement);

var automaticPlay = true;
var manualTime=0;

gui.add({Progress: 0}, "Progress", 0, maxTime, 0.01).onChange(function (value) {
    automaticPlay = false;
	manualTime = value+0.0001;
	btn.innerHTML = "&#9654";
})
customContainer.getElementsByClassName('c')[0].style.width = (canvas.clientWidth-20).toString()+'px';
customContainer.getElementsByClassName('dg main')[0].style.width = canvas.clientWidth.toString()+'px';
customContainer.getElementsByClassName('dg main')[0].style.right = '0px'; //0
customContainer.getElementsByClassName('dg main')[0].style.top = '0px'; //550
customContainer.getElementsByClassName('dg main')[0].style.position = 'relative'; //absolute
customContainer.getElementsByClassName('close-button close-bottom')[0].style.height = '0px';
customContainer.getElementsByClassName('close-button close-bottom')[0].innerHTML = '';
customContainer.getElementsByClassName('property-name')[0].innerHTML = '';
customContainer.getElementsByClassName('slider')[0].style.width = (canvas.clientWidth-100).toString()+'px'
customContainer.getElementsByClassName('slider-fg')[0].style.backgroundColor = '#19bd39'
customContainer.querySelectorAll("input[type=text]")[0].style.width = '50px';
customContainer.querySelectorAll("input[type=text]")[0].style.color = '#19bd39';

customContainer.getElementsByClassName('dg')[0].style.borderLeft = '4px solid #1a1a1a'
customContainer.getElementsByClassName('cr')[0].style.borderLeft = '4px solid #1a1a1a'
customContainer.getElementsByClassName('number')[0].style.borderLeft = '4px solid #1a1a1a'
var recoveryCurrentTime = false;

let btn = document.createElement("button");
btn.style.backgroundColor = "#1a1a1a";
btn.style.color = "#19bd39";
btn.style.border= "none";
btn.style.height= "28px";
btn.style.width= "28px";
btn.innerHTML = "||";
btn.onclick = function () {

	automaticPlay = !automaticPlay;

	if(automaticPlay)
	{
		btn.innerHTML = "||";
		recoveryCurrentTime = true;
	}
	else
	{
		manualTime = parseFloat(customContainer.querySelectorAll("input[type=text]")[0].value)+0.0001;
		btn.innerHTML = "&#9654";
	}

};
customContainer.getElementsByClassName('c')[0].style.verticalAlign= "middle"
customContainer.getElementsByClassName('c')[0].appendChild(btn);
//------------------------------------------------------------

//Wait until all objects loaded

var loadedAll = false;
var sceneDrawn = false;


//Get starting ms
var startMs =  elapsedMs()

//Initialize
var heightScene;
var heightBar;

document.getElementsByClassName('controller')[0].appendChild(customContainer.getElementsByClassName('dg main')[0])
document.getElementsByClassName('controller')[0].style.opacity="0"

heightScene = document.getElementById('scene_'+sceneID).style.height;
document.getElementById('scene_'+sceneID).style.visibility='hidden';
document.getElementById('scene_'+sceneID).style.height='0px';

heightBar = customContainer.getElementsByClassName('dg main')[0].style.height;
customContainer.getElementsByClassName('dg main')[0].style.visibility='hidden';
customContainer.getElementsByClassName('dg main')[0].style.height = '0px';


//-------------------- THE ANIMATION LOOP -------------------



renderer.setAnimationLoop(() => {


	loadedAll = true;

	for(let i = 0; i < sceneElements.length; i++){
		loadedAll = loadedAll && sceneElements[i].hasLoaded();
	}

	if(!loadedAll)
	{
		startMs =  elapsedMs();
	}
	else
	{
		//document.getElementById('canvas_container').style.visibility = 'visible';
		if( (elapsedMs()-startMs > delay) && !sceneDrawn)
		{
			document.getElementById('scene_'+sceneID).style.visibility = 'visible';
			document.getElementById('canvas_container_'+sceneID).getElementsByClassName('dg main')[0].style.visibility = 'visible';
			document.getElementById('scene_'+sceneID).style.height=heightScene;
			document.getElementById('canvas_container_'+sceneID).getElementsByClassName('dg main')[0].style.height = heightBar;
			document.getElementById('loading_screen_'+sceneID).remove();
			sceneDrawn = true;
		}
	}


	//MAGIC HAPPENS HERE!!!
	if(loadedAll && automaticPlay)
	{

		var currentSeconds;
		if(!recoveryCurrentTime)
		{

			for (let i = 0; i < sceneElements.length; i++) {
				sceneElements[i].nextFrame();
				sceneElements[i].showFrame();
			}

			currentSeconds = Math.min(0.001*Math.max(elapsedMs()-startMs-delay,0),maxTime);

			var percentage = (100 * currentSeconds / (0.000001 + maxTime)).toString();
			customContainer.getElementsByClassName('slider-fg')[0].style.width = percentage + "%";
			customContainer.querySelectorAll("input[type=text]")[0].value = Math.round(100 * currentSeconds) / 100;
		}
		else
		{
			currentSeconds = customContainer.querySelectorAll("input[type=text]")[0].value;
			startMs =  elapsedMs()-delay-1000*currentSeconds;
			recoveryCurrentTime = false;
		}

	}
	if(loadedAll && !automaticPlay)
	{
		for (let i = 0; i < sceneElements.length; i++) {
			sceneElements[i].setFrameTime(manualTime);
			sceneElements[i].showFrame();
		}
	}

	renderer.render(scene, camera);
});
//------------------------------------------------------------