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

import props from './props';
import { tempQuaternion, tempVector, createInstancedMesh } from './utils/three';
import viewer from './viewer';
import settings from './settings';
import storage from './storage';
import { getCostumeColor } from './theme/colors';

const num = 20;
let roomIndex = 0;
let roomMesh;

export default class Room {
  constructor(url) {
    this.index = roomIndex++;

    const costumeColor = getCostumeColor(this.index);

    if (!roomMesh) {
      roomMesh = createInstancedMesh(
        num,
        getCostumeColor(0),
        props.space.geometry,
      );
      viewer.scene.add(roomMesh);
    }

    this.handMesh = createInstancedMesh(
      200,
      costumeColor,
      props.hand.geometry,
    );
    viewer.scene.add(this.handMesh);


    this.headMesh = createInstancedMesh(
      200,
      costumeColor,
      props.head.geometry,
    );
    viewer.scene.add(this.headMesh);


    this.url = url;
    this.position = new THREE.Vector3();
    this.setPosition(0,
      settings.roomHeight * 0.5,
      settings.roomOffset + (this.index * (settings.roomDepth + 0.001)),
    );
  }

  load(callback) {
    storage.load(this.url, (error, performances) => {
      if (error) return callback(error);
      this.performances = performances;
      callback();
    });
  }

  setPosition(x, y, z) {
    const position = this.position;
    position.x = x;
    position.y = y;
    position.z = z;
    roomMesh.setPositionAt(this.index, tempVector(x, y, z));
  }

  moveHead(index, [x, y, z, qx, qy, qz, qw]) {
    this.headMesh.setQuaternionAt(index, tempQuaternion(qx, qy, qz, qw));
    this.headMesh.setPositionAt(index, tempVector(x, y, z + this.position.z - settings.roomOffset));
  }

  moveHand(index, [x, y, z, qx, qy, qz, qw]) {
    this.handMesh.setQuaternionAt(index, tempQuaternion(qx, qy, qz, qw));
    this.handMesh.setPositionAt(index, tempVector(x, y, z + this.position.z - settings.roomOffset));
  }

  updateLimbs() {
    this.headMesh.needsUpdate();
    this.handMesh.needsUpdate();
  }

  gotoTime(time) {
    let seconds = time * 0.001;

    // Offset every other room in time by half a loop, so whenever our floating
    // camera enters the room, we are seeing a recording:
    if (this.index % 2 === 0) {
      seconds += settings.loopSeconds;
    }

    const number = Math.floor((seconds % (settings.loopSeconds * 2)) * 90);

    if (!this.performances) return;
    for (let i = 0; i < this.performances.length; i++) {
      const frames = this.performances[i];
      const [head, left, right] = frames[number % frames.length];
      this.moveHead(i, head);
      this.moveHand(i * 2, left);
      this.moveHand((i * 2) - 1, right);
    }
    this.updateLimbs();
  }

  update() {
    roomMesh.needsUpdate('position');
  }
}

@@ -417,18 +417,97 @@
 oomIndex
-++
+;%0A    roomIndex += 1;%0A    this.url = url;%0A    this.position = new THREE.Vector3()
 ;%0A%0A    c
@@ -732,24 +732,162 @@
 sh);%0A    %7D%0A%0A
+    this.setPosition(0,%0A      settings.roomHeight * 0.5,%0A      settings.roomOffset + (this.index * (settings.roomDepth + 0.001)),%0A    );%0A%0A
     this.han
@@ -1166,208 +1166,8 @@
 h);%0A
-%0A%0A    this.url = url;%0A    this.position = new THREE.Vector3();%0A    this.setPosition(0,%0A      settings.roomHeight * 0.5,%0A      settings.roomOffset + (this.index * (settings.roomDepth + 0.001)),%0A    );%0A
   %7D%0A
@@ -1540,249 +1540,75 @@
 ;%0A  
-%7D%0A%0A  moveHead(index, %5Bx, y, z, qx, qy, qz, qw%5D) %7B%0A    this.headMesh.setQuaternionAt(index, tempQuaternion(qx, qy, qz, qw));%0A    this.headMesh.setPositionAt(index, tempVector(x, y, z + this.position.z - settings.roomOffset));%0A  %7D%0A%0A  moveHand(
+  roomMesh.needsUpdate('position');%0A  %7D%0A%0A  moveMesh(instancedMesh, 
 inde
@@ -1639,32 +1639,32 @@
  qw%5D) %7B%0A    
-this.han
+instance
 dMesh.setQua
@@ -1713,32 +1713,32 @@
 , qw));%0A    
-this.han
+instance
 dMesh.setPos
@@ -1820,74 +1820,18 @@
 ;%0A  
-%7D%0A%0A  updateLimbs() %7B%0A    this.headMesh.needsUpdate();%0A    this.han
+  instance
 dMes
@@ -2418,13 +2418,28 @@
 move
-Head(
+Mesh(this.headMesh, 
 i, h
@@ -2459,21 +2459,36 @@
 his.move
-Hand(
+Mesh(this.handMesh, 
 i * 2, l
@@ -2512,21 +2512,36 @@
 move
-Hand(
+Mesh(this.handMesh, 
 (i * 2) 
 - 1,
@@ -2536,17 +2536,17 @@
 (i * 2) 
--
++
  1, righ
@@ -2559,88 +2559,8 @@
   %7D%0A
-    this.updateLimbs();%0A  %7D%0A%0A  update() %7B%0A    roomMesh.needsUpdate('position');%0A
   %7D%0A

simplify room