using System;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.Rendering;

namespace Leap.Unity
{
	[RequireComponent(typeof(Camera))]
	[ExecuteInEditMode]
	public class LeapVRCameraControl : MonoBehaviour
	{
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public static event Action<LeapVRCameraControl.CameraParams> OnValidCameraParams;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public static event Action<Camera> OnLeftPreRender;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public static event Action<Camera> OnRightPreRender;

		public bool OverrideEyePosition
		{
			get
			{
				return this._overrideEyePosition;
			}
			set
			{
				this._overrideEyePosition = value;
			}
		}

		private Camera _camera
		{
			get
			{
				if (this._cachedCamera == null)
				{
					this._cachedCamera = base.GetComponent<Camera>();
				}
				return this._cachedCamera;
			}
		}

		private void Start()
		{
			this._deviceInfo = new LeapDeviceInfo(LeapDeviceType.Peripheral);
		}

		private void Update()
		{
			LeapVRCameraControl._hasDispatchedValidCameraParams = false;
		}

		private void OnPreCull()
		{
			this._camera.ResetWorldToCameraMatrix();
			this._finalCenterMatrix = this._camera.worldToCameraMatrix;
			if (!LeapVRCameraControl._hasDispatchedValidCameraParams)
			{
				LeapVRCameraControl.CameraParams obj = new LeapVRCameraControl.CameraParams(this._cachedCamera);
				if (LeapVRCameraControl.OnValidCameraParams != null)
				{
					LeapVRCameraControl.OnValidCameraParams(obj);
				}
				LeapVRCameraControl._hasDispatchedValidCameraParams = true;
			}
		}

		private void OnPreRender()
		{
			this._eyeType.BeginCamera();
			if (this._eyeType.IsLeftEye)
			{
				Shader.SetGlobalVector("_LeapGlobalStereoUVOffset", LeapVRCameraControl.LEFT_EYE_UV_OFFSET);
				if (LeapVRCameraControl.OnLeftPreRender != null)
				{
					LeapVRCameraControl.OnLeftPreRender(this._cachedCamera);
				}
			}
			else
			{
				Shader.SetGlobalVector("_LeapGlobalStereoUVOffset", LeapVRCameraControl.RIGHT_EYE_UV_OFFSET);
				if (LeapVRCameraControl.OnRightPreRender != null)
				{
					LeapVRCameraControl.OnRightPreRender(this._cachedCamera);
				}
			}
			Matrix4x4 matrix4x;
			if (this._overrideEyePosition)
			{
				matrix4x = this._finalCenterMatrix;
				Vector3 a = (float)((!this._eyeType.IsLeftEye) ? -1 : 1) * base.transform.right * this._deviceInfo.baseline * 0.5f;
				Vector3 b = -base.transform.forward * this._deviceInfo.focalPlaneOffset;
				matrix4x *= Matrix4x4.TRS(a + b, Quaternion.identity, Vector3.one);
			}
			else
			{
				matrix4x = this._camera.worldToCameraMatrix;
			}
			this._camera.worldToCameraMatrix = matrix4x;
		}

		public const string GLOBAL_EYE_UV_OFFSET_NAME = "_LeapGlobalStereoUVOffset";

		private static Vector2 LEFT_EYE_UV_OFFSET = new Vector2(0f, 0f);

		private static Vector2 RIGHT_EYE_UV_OFFSET = new Vector2(0f, 0.5f);

		private static bool _hasDispatchedValidCameraParams = false;

		[SerializeField]
		private EyeType _eyeType = new EyeType(EyeType.OrderType.CENTER);

		[SerializeField]
		private bool _overrideEyePosition = true;

		private Camera _cachedCamera;

		private Matrix4x4 _finalCenterMatrix;

		private LeapDeviceInfo _deviceInfo;

		public struct CameraParams
		{
			public CameraParams(Camera camera)
			{
				this.CenterEyeTransform = camera.transform;
				this.ProjectionMatrix = camera.projectionMatrix;
				GraphicsDeviceType graphicsDeviceType = SystemInfo.graphicsDeviceType;
				if (graphicsDeviceType == GraphicsDeviceType.Direct3D9 || graphicsDeviceType == GraphicsDeviceType.Direct3D11 || graphicsDeviceType == GraphicsDeviceType.Direct3D12)
				{
					for (int i = 0; i < 4; i++)
					{
						this.ProjectionMatrix[1, i] = -this.ProjectionMatrix[1, i];
					}
					for (int j = 0; j < 4; j++)
					{
						this.ProjectionMatrix[2, j] = this.ProjectionMatrix[2, j] * 0.5f + this.ProjectionMatrix[3, j] * 0.5f;
					}
				}
				this.Width = camera.pixelWidth;
				this.Height = camera.pixelHeight;
			}

			public readonly Transform CenterEyeTransform;

			public readonly Matrix4x4 ProjectionMatrix;

			public readonly int Width;

			public readonly int Height;
		}
	}
}
