/**
 * @author mrdoob / http://mrdoob.com/
 */

import { PerspectiveCamera } from './PerspectiveCamera.js';
import { Vector3 } from '../math/Vector3.js';

function ArrayCamera( array ) {

	PerspectiveCamera.call( this );

	this.cameras = array || [];

}

ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {

	constructor: ArrayCamera,

	isArrayCamera: true,

	/**
	 * Assumes 2 cameras that are perpendicular and share an X-axis, and that
	 * the cameras' projection and world matrices have already been set.
	 * And that near and far planes are identical for both cameras.
	 */
	setProjectionFromUnion: function () {
		var cameraLPos = new Vector3();
		var cameraRPos = new Vector3();

		return function () {
			cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld );
			cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld );

			var ipd = cameraLPos.distanceTo( cameraRPos );

			var projL = this.cameras[ 0 ].projectionMatrix;
			var projR = this.cameras[ 1 ].projectionMatrix;

			// VR systems will have identical far and near planes, and
			// most likely identical top and bottom frustum extents.
			// via: https://computergraphics.stackexchange.com/a/4765
			var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
			var far = projL[ 14 ] / ( projL[ 10 ] + 1 );

			var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
			var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
			var leftL = leftFovL * near;
			var rightR = rightFovR * near;
			var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
			var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
			var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
			var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];

			// Calculate the new camera's position offset from the
			// left camera.
			var zOffset = ipd / (leftFovL + rightFovR);
			var xOffset = zOffset * leftFovL;

			// TODO: Better way to apply this offset?
			this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale );
			this.translateX(xOffset);
			this.translateZ(-zOffset);
			this.matrixWorld.compose( this.position, this.quaternion, this.scale );
			this.matrixWorldInverse.getInverse(this.matrixWorld);

			// Find the union of the frustum values of the cameras and scale
			// the values so that the near plane's position does not change in world space,
			// although must now be relative to the new union camera.
			var near2 = near + zOffset;
			var far2 = far + zOffset;
			var left = leftL - xOffset;
			var right = rightR + (ipd - xOffset)
			var top = Math.max( topL, topR );
			var bottom = Math.min( bottomL, bottomR );

			this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
		}
	}(),

} );


export { ArrayCamera };

@@ -646,16 +646,17 @@
 on () %7B%0A
+%0A
 %09%09var ca
@@ -739,16 +739,17 @@
 on () %7B%0A
+%0A
 %09%09%09camer
@@ -1809,16 +1809,17 @@
  ipd / (
+ 
 leftFovL
@@ -1830,16 +1830,17 @@
 ightFovR
+ 
 );%0A%09%09%09va
@@ -2026,23 +2026,25 @@
 nslateX(
+ 
 xOffset
+ 
 );%0A%09%09%09th
@@ -2061,16 +2061,19 @@
 teZ(
--
+ - 
 zOffset
+ 
 );%0A%09
@@ -2184,16 +2184,17 @@
 Inverse(
+ 
 this.mat
@@ -2201,16 +2201,17 @@
 rixWorld
+ 
 );%0A%0A%09%09%09/
@@ -2534,16 +2534,17 @@
 ghtR + (
+ 
 ipd - xO
@@ -2548,17 +2548,19 @@
  xOffset
-)
+ );
 %0A%09%09%09var 
@@ -2723,11 +2723,14 @@
  );%0A
+%0A
 %09%09%7D
+;%0A
 %0A%09%7D(

Fix code style to match ESLint requirements.