'use strict';

var matrixToCSS = require('matrix-to-css');
var mat4 = require('gl-mat4');
var createMesh = require('gl-mesh');
var glslify = require('glslify');

module.exports = function(element, opts) {
  return new GLCSS3D(element, opts);
};

function GLCSS3D(element, opts) {
  if (!element) throw new Error('gl-css3d requires element');

  var domElement = document.createElement('div');
  domElement.style.transformStyle = domElement.style.webkitTransformStyle = 'preserve-3d';
  domElement.style.overflow = 'hidden';
  domElement.style.pointerEvents = 'none';
  domElement.style.position = 'absolute';
  domElement.style.zIndex = '-1'; // below WebGL canvas
  domElement.style.top = '0';
  domElement.style.left = '0';
  domElement.style.margin = '0';
  domElement.style.padding = '0';

  var cameraElement = document.createElement('div');
  cameraElement.style.position = 'absolute';
  cameraElement.style.transformStyle = cameraElement.style.webkitTransformStyle = 'preserve-3d';
  //cameraElement.style.display = 'none';
  cameraElement.style.pointerEvents = 'auto'; // allow mouse interaction

  cameraElement.appendChild(element);

  domElement.appendChild(cameraElement);
  document.body.appendChild(domElement);

  this.domElement = domElement;
  this.cameraElement = cameraElement;

  opts = opts || {};

  this.planeWidth = opts.planeWidth || 2; // assume -1 to +1
  this.planeHeight = opts.planeHeight || 2;
  //this.tint = opts.tint || [0.5,0,0,0]; // reddish tint, etc.. useful? (note gl blending mode)
  this.tint = opts.tint || [0,0,0,0]; // fully transparent
  this.blend = (opts.blend !== undefined) ? opts.blend : false; // overwrite transparent color

  this.cutoutMesh = null;
  this.cutoutShader = null;
  this.gl = null;
}

GLCSS3D.prototype.ginit = function(gl) {
  this.gl = gl;
  var hx = this.planeWidth / 2;
  var hy = this.planeHeight / 2;
  this.cutoutMesh = createMesh(gl,
        [
        [2, 1, 0],
        [3, 1, 2]
         ],
        { "position": [
          [-hx, -hy, 0],
          [-hx, +hy, 0],
          [+hx, -hy, 0],
          [+hx, +hy, 0]] })

  this.cutoutShader = glslify({
      inline: true,
      vertex: "\
  attribute vec3 position;\
  \
  uniform mat4 projection;\
  uniform mat4 view;\
  \
  void main() {\
    gl_Position = projection * view * vec4(position, 1.0);\
  }",

    // color it all transparent so CSS element is visible through
    fragment: "\
  precision highp float;\
  uniform vec4 color;\
  \
  void main() {\
    gl_FragColor = color;\
  }"})(gl)
};

GLCSS3D.prototype.updatePerspective = function(cameraFOVradians, width, height) {
  // CSS world perspective - only needs to change on gl-resize (not each rendering tick)
  var fovPx = 0.5 / Math.tan(cameraFOVradians / 2) * height;
  this.domElement.style.perspective = this.domElement.style.webkitPerspective = fovPx + 'px';
  //domElement.style.perspectiveOrigin = '50% 50%'; // already is the default
  this.domElement.style.width = width + 'px';
  this.domElement.style.height = height + 'px';

  this.fovPx = fovPx;

  // CSS camera element child
  this.cameraElement.style.width = width + 'px';
  this.cameraElement.style.height = height + 'px';

  this.width = width;
  this.height = height;
};

var cssMatrix = mat4.create();

GLCSS3D.prototype.updateView= function(view) {
  var scaleX = -this.planeWidth / this.width;
  var scaleY = -this.planeHeight / this.height;
  var scaleZ = 1;
  mat4.scale(cssMatrix, view, [scaleX, scaleY, scaleZ]);

  // three.js CSS3Renderer getCameraCSSMatrix inverts these to fix flipped rotation orientation
  // TODO: matrix transformation instead?
  cssMatrix[1] = -cssMatrix[1];
  cssMatrix[5] = -cssMatrix[5];
  cssMatrix[9] = -cssMatrix[9];
  cssMatrix[13] = -cssMatrix[13];

  this.cameraElement.style.transform = this.cameraElement.style.webkitTransform = 'translateZ('+this.fovPx+'px) ' + matrixToCSS(cssMatrix);
};

GLCSS3D.prototype.renderCutout = function(view, proj) {
  this.cutoutShader.bind()
  this.cutoutShader.attributes.position.location = 0

  this.cutoutShader.uniforms.projection = proj
  this.cutoutShader.uniforms.view = view
  this.cutoutShader.uniforms.color = this.tint

  this.cutoutMesh.bind(this.cutoutShader)

  if (!this.blend) this.gl.disable(this.gl.BLEND);
  this.cutoutMesh.draw()
  if (!this.blend) this.gl.enable(this.gl.BLEND); // TODO: use module to push/restore gl state?

  this.cutoutMesh.unbind()
};


GLCSS3D.prototype.render = function(view, proj) {
  this.updateView(view);
  this.renderCutout(view, proj);
};

@@ -1668,16 +1668,142 @@
 nt color
+%0A  this.flipX = (opts.flipX !== undefined) ? opts.flipX : true;%0A  this.flipY = (opts.flipY !== undefined) ? opts.flipY : true;
 %0A%0A  this
@@ -3412,16 +3412,17 @@
 dateView
+ 
 = functi
@@ -3447,17 +3447,16 @@
 caleX = 
--
 this.pla
@@ -3492,17 +3492,16 @@
 caleY = 
--
 this.pla
@@ -3542,16 +3542,88 @@
 eZ = 1;%0A
+  if (this.flipX) scaleX = -scaleX;%0A  if (this.flipY) scaleY = -scaleY;%0A
   mat4.s

Add flipX and flipY options