var text = "three.js",

  height = 20,
  size = 70,
  hover = 30,

  curveSegments = 4,

  bevelThickness = 2,
  bevelSize = 1.5,
  bevelSegments = 3,
  bevelEnabled = true,

  font = undefined,

  fontName = "optimer", // helvetiker, optimer, gentilis, droid sans, droid serif
  fontWeight = "bold"; // normal bold

var mirror = true;

var fontMap = {

  "helvetiker": 0,
  "optimer": 1,
  "gentilis": 2,
  "droid/droid_sans": 3,
  "droid/droid_serif": 4

};

var weightMap = {

  "regular": 0,
  "bold": 1

};

var reverseFontMap = [];
var reverseWeightMap = [];

for (var i in fontMap) reverseFontMap[fontMap[i]] = i;
for (var i in weightMap) reverseWeightMap[weightMap[i]] = i;

var targetRotation = 0;
var targetRotationOnMouseDown = 0;

var mouseX = 0;
var mouseXOnMouseDown = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var fontIndex = 1;

function decimalToHex(d) {

  var hex = Number(d).toString(16);
  hex = "000000".substr(0, 6 - hex.length) + hex;
  return hex.toUpperCase();

}


function loadFont() {

  var loader = new THREE.FontLoader();
  loader.load('fonts/' + fontName + '_' + fontWeight + '.typeface.json', function(response) {

    font = response;

    refreshText();

  });
}

function createText() {

  textGeo = new THREE.TextBufferGeometry(text, {

    font: font,

    size: size,
    height: height,
    curveSegments: curveSegments,

    bevelThickness: bevelThickness,
    bevelSize: bevelSize,
    bevelEnabled: bevelEnabled,

    material: 0,
    extrudeMaterial: 1

  });

  textGeo.computeBoundingBox();
  textGeo.computeVertexNormals();

  // "fix" side normals by removing z-component of normals for side faces
  // (this doesn't work well for beveled geometry as then we lose nice curvature around z-axis)

  if (!bevelEnabled) {

    var triangleAreaHeuristics = 0.1 * (height * size);

    for (var i = 0; i < textGeo.faces.length; i++) {

      var face = textGeo.faces[i];

      if (face.materialIndex == 1) {

        for (var j = 0; j < face.vertexNormals.length; j++) {

          face.vertexNormals[j].z = 0;
          face.vertexNormals[j].normalize();

        }

        var va = textGeo.vertices[face.a];
        var vb = textGeo.vertices[face.b];
        var vc = textGeo.vertices[face.c];

        var s = THREE.GeometryUtils.triangleArea(va, vb, vc);

        if (s > triangleAreaHeuristics) {

          for (var j = 0; j < face.vertexNormals.length; j++) {

            face.vertexNormals[j].copy(face.normal);

          }

        }

      }

    }

  }

  var centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);

  textMesh1 = new THREE.Mesh(textGeo, materials);

  textMesh1.position.x = centerOffset;
  textMesh1.position.y = hover;
  textMesh1.position.z = 0;

  textMesh1.rotation.x = 0;
  textMesh1.rotation.y = Math.PI * 2;

  group.add(textMesh1);

  if (mirror) {

    textMesh2 = new THREE.Mesh(textGeo, materials);

    textMesh2.position.x = centerOffset;
    textMesh2.position.y = -hover;
    textMesh2.position.z = height;

    textMesh2.rotation.x = Math.PI;
    textMesh2.rotation.y = Math.PI * 2;

    group.add(textMesh2);

  }

}

function refreshText() {

  group.remove(textMesh1);
  if (mirror) group.remove(textMesh2);

  if (!text) return;

  createText();

}
