import asyncMap from 'async/map';
import emitter from 'mitt';

import * as THREE from './lib/three';

// import roomUrl from './public/models/obj/space-bigger-holes.obj';
import roomUrl from './public/models/obj/space-bigger-holes-ao.obj';
import isometricRoomUrl from './public/models/obj/space-isometric.obj';
import settings from './settings';

require('./lib/OBJLoader')(THREE);

const {
  OBJLoader,
  TextureLoader,
  Mesh,
  MeshLambertMaterial,
  MeshBasicMaterial,
  ConeBufferGeometry,
  CylinderBufferGeometry,
  SphereGeometry,
  GridHelper,
  Group,
  Object3D,
} = THREE;

const loadObject = (url, callback) => {
  new OBJLoader().load(url,
    object => callback(null, object.children[0]),
    () => {},
    (err) => { callback(err); },
  );
};

const thumbpadMaterial = new MeshLambertMaterial({ color: settings.textColor });
const controllerMaterial = new MeshLambertMaterial({ color: settings.controllerColor });

const props = Object.assign(emitter(), {
  hand: (function createHand() {
    const radius = 0.02;
    const height = 0.2;
    const segments = 32;
    const cylinder = new Mesh(
      new CylinderBufferGeometry(radius, radius, height, segments),
      new MeshLambertMaterial({ color: settings.controllerColor }),
    );

    cylinder.rotation.x = Math.PI * 0.5 * 7;
    cylinder.updateMatrix();
    cylinder.geometry.applyMatrix(cylinder.matrix);
    return cylinder;
  }()),

  controller: (function createHand() {
    const radius = 0.02;
    const height = 0.2;
    const segments = 32;
    const cylinder = new Mesh(
      new CylinderBufferGeometry(radius, radius, height, segments),
      controllerMaterial,
    );
    cylinder.rotation.x = Math.PI * 0.5 * 7;
    cylinder.updateMatrix();

    const thumbpadRadius = 0.015;
    const thumbpadHeight = 0.02;
    const thumbpad = new THREE.Mesh(
      new CylinderBufferGeometry(thumbpadRadius, thumbpadRadius, thumbpadHeight, segments),
      thumbpadMaterial
    );
    thumbpad.position.z = -0.05;
    thumbpad.position.y = 0.01;
    thumbpad.updateMatrix();

    const group = new Group();

    group.add(cylinder, thumbpad);

    return group;
  }()),

  head: (function createHead() {
    const radius = 0.12;
    const height = 0.2;
    const segments = 32;
    const cone = new Mesh(
      new ConeBufferGeometry(radius, height, segments),
      new MeshLambertMaterial({ color: settings.controllerColor }),
    );

    cone.rotation.x = Math.PI * 0.5 * 7;
    cone.updateMatrix();
    cone.geometry.applyMatrix(cone.matrix);
    return cone;
  }()),

  sphere: (function createSphere() {
    const segments = 32;
    const geometry = new SphereGeometry(
      settings.sphereRadius,
      segments,
      segments,
    );
    const material = new MeshBasicMaterial({
      color: settings.sphereColor.clone(),
    });
    return new Mesh(geometry, material);
  }()),

  grid: (function createGrid() {
    return new GridHelper(50, 50, 0xaaaa00, 0xaaaa00);
  }()),

  thumbpadMaterial
});

const textureLoader = new TextureLoader();

asyncMap(
  [roomUrl, isometricRoomUrl],
  loadObject,
  (error, [room, isometricRoom]) => {
    if (error) throw error;
    props.room = room;

    props.room.material = new THREE.MeshLambertMaterial();
    textureLoader.load('public/models/obj/bake/baked_tpAmbient_cubeMesh.png', function( texture ){
      props.room.material.map = texture;

      //  TODO / BUG / FIXME
      //  if 'loaded' is fired before this, reloading record mode
      //  will result in the room material to not have this texture
      props.emit('loaded');
    });

    props.orthographicRoom = isometricRoom;
  },
);

export default props;

@@ -560,20 +560,8 @@
 up,%0A
-  Object3D,%0A
 %7D = 
@@ -595,25 +595,61 @@
 (url
-, callback
+) =%3E %7B%0A  return new Promise((resolve, reject
 ) =%3E %7B%0A
+  
   ne
@@ -676,16 +676,18 @@
 rl,%0A    
+  
 object =
@@ -692,23 +692,16 @@
  =%3E 
-callback(null, 
+resolve(
 obje
@@ -721,16 +721,18 @@
 %5D),%0A    
+ 
+ 
 () =%3E %7B%7D
@@ -741,44 +741,212 @@
     
-(err) =%3E %7B callback(err); %7D,%0A  );%0A%7D;
+  reject,%0A    );%0A  %7D);%0A%7D;%0A%0Aconst preloadTexture = (url) =%3E %7B%0A  return new Promise((resolve, reject) =%3E %7B%0A    new TextureLoader().load(%0A      url,%0A      resolve,%0A      () =%3E %7B%7D,%0A      reject%0A    );%0A  %7D);%0A%7D
 %0A%0Aco
@@ -3167,80 +3167,65 @@
 rial
+,
 %0A%7D);%0A%0A
-const textureLoader = new TextureLoader();%0A%0AasyncMap(%0A  %5BroomUrl, 
+Promise.all(%5B%0A  loadObject(roomUrl),%0A  loadObject(
 isom
@@ -3240,269 +3240,217 @@
 mUrl
-%5D
+)
 ,%0A  
+pre
 load
-Object,%0A  (error, %5Broom, isometricRoom%5D) =%3E %7B%0A    if (error) throw error;%0A    props.room = room;%0A%0A    props.room.material = new THREE.MeshLambertMaterial();%0A    textureLoader.load('public/models/obj/bake/baked_tpAmbient_cubeMesh.png', function(
+Texture('public/models/obj/bake/baked_tpAmbient_cubeMesh.png'),%0A%5D)%0A  .then((%5Broom, isometricRoom, texture%5D) =%3E %7B%0A    room.material = new THREE.MeshLambertMaterial();%0A    room.material.map =
  texture
  )%7B%0A
@@ -3449,14 +3449,11 @@
 ture
- )%7B%0A  
+;%0A%0A
     
@@ -3466,283 +3466,172 @@
 room
-.material.map = texture;%0A%0A      //  TODO / BUG / FIXME%0A      //  if 'loaded' is fired before this, reloading record mode%0A      //  will result in the room material to not have this texture%0A      props.emit('loaded');%0A    %7D);%0A%0A    props.orthographicRoom = isometricRoom
+ = room;%0A    props.orthographicRoom = isometricRoom;%0A    props.emit('loaded');%0A  %7D)%0A  .catch((error) =%3E %7B%0A    // TODO: goto error screen%0A    console.log(error)
 ;%0A  %7D
-,%0A
 );%0A%0A

improve props preload