using System;
using System.Text;
using UnityEngine;
using UnityEngine.VR;
using Valve.VR;

public class SteamVR : IDisposable
{
	private SteamVR()
	{
		this.hmd = OpenVR.System;
		Debug.Log("Connected to " + this.hmd_TrackingSystemName + ":" + this.hmd_SerialNumber);
		this.compositor = OpenVR.Compositor;
		this.overlay = OpenVR.Overlay;
		uint num = 0u;
		uint num2 = 0u;
		this.hmd.GetRecommendedRenderTargetSize(ref num, ref num2);
		this.sceneWidth = num;
		this.sceneHeight = num2;
		float num3 = 0f;
		float num4 = 0f;
		float num5 = 0f;
		float num6 = 0f;
		this.hmd.GetProjectionRaw(EVREye.Eye_Left, ref num3, ref num4, ref num5, ref num6);
		float num7 = 0f;
		float num8 = 0f;
		float num9 = 0f;
		float num10 = 0f;
		this.hmd.GetProjectionRaw(EVREye.Eye_Right, ref num7, ref num8, ref num9, ref num10);
		this.tanHalfFov = new Vector2(Mathf.Max(new float[]
		{
			-num3,
			num4,
			-num7,
			num8
		}), Mathf.Max(new float[]
		{
			-num5,
			num6,
			-num9,
			num10
		}));
		this.textureBounds = new VRTextureBounds_t[2];
		this.textureBounds[0].uMin = 0.5f + 0.5f * num3 / this.tanHalfFov.x;
		this.textureBounds[0].uMax = 0.5f + 0.5f * num4 / this.tanHalfFov.x;
		this.textureBounds[0].vMin = 0.5f - 0.5f * num6 / this.tanHalfFov.y;
		this.textureBounds[0].vMax = 0.5f - 0.5f * num5 / this.tanHalfFov.y;
		this.textureBounds[1].uMin = 0.5f + 0.5f * num7 / this.tanHalfFov.x;
		this.textureBounds[1].uMax = 0.5f + 0.5f * num8 / this.tanHalfFov.x;
		this.textureBounds[1].vMin = 0.5f - 0.5f * num10 / this.tanHalfFov.y;
		this.textureBounds[1].vMax = 0.5f - 0.5f * num9 / this.tanHalfFov.y;
		this.sceneWidth /= Mathf.Max(this.textureBounds[0].uMax - this.textureBounds[0].uMin, this.textureBounds[1].uMax - this.textureBounds[1].uMin);
		this.sceneHeight /= Mathf.Max(this.textureBounds[0].vMax - this.textureBounds[0].vMin, this.textureBounds[1].vMax - this.textureBounds[1].vMin);
		this.aspect = this.tanHalfFov.x / this.tanHalfFov.y;
		this.fieldOfView = 2f * Mathf.Atan(this.tanHalfFov.y) * 57.29578f;
		this.eyes = new SteamVR_Utils.RigidTransform[]
		{
			new SteamVR_Utils.RigidTransform(this.hmd.GetEyeToHeadTransform(EVREye.Eye_Left)),
			new SteamVR_Utils.RigidTransform(this.hmd.GetEyeToHeadTransform(EVREye.Eye_Right))
		};
		if (SystemInfo.graphicsDeviceVersion.StartsWith("OpenGL"))
		{
			this.graphicsAPI = EGraphicsAPIConvention.API_OpenGL;
		}
		else
		{
			this.graphicsAPI = EGraphicsAPIConvention.API_DirectX;
		}
		SteamVR_Utils.Event.Listen("initializing", new SteamVR_Utils.Event.Handler(this.OnInitializing));
		SteamVR_Utils.Event.Listen("calibrating", new SteamVR_Utils.Event.Handler(this.OnCalibrating));
		SteamVR_Utils.Event.Listen("out_of_range", new SteamVR_Utils.Event.Handler(this.OnOutOfRange));
		SteamVR_Utils.Event.Listen("device_connected", new SteamVR_Utils.Event.Handler(this.OnDeviceConnected));
		SteamVR_Utils.Event.Listen("new_poses", new SteamVR_Utils.Event.Handler(this.OnNewPoses));
	}

	public static bool active
	{
		get
		{
			return SteamVR._instance != null;
		}
	}

	public static bool enabled
	{
		get
		{
			return SteamVR._enabled;
		}
		set
		{
			SteamVR._enabled = value;
			if (!SteamVR._enabled)
			{
				SteamVR.SafeDispose();
			}
		}
	}

	public static SteamVR instance
	{
		get
		{
			if (!SteamVR.enabled)
			{
				return null;
			}
			if (SteamVR._instance == null)
			{
				SteamVR._instance = SteamVR.CreateInstance();
				if (SteamVR._instance == null)
				{
					SteamVR._enabled = false;
				}
			}
			return SteamVR._instance;
		}
	}

	public static bool usingNativeSupport
	{
		get
		{
			return VRDevice.GetNativePtr() != IntPtr.Zero;
		}
	}

	private static SteamVR CreateInstance()
	{
		try
		{
			EVRInitError evrinitError = EVRInitError.None;
			if (!SteamVR.usingNativeSupport)
			{
				Debug.Log("OpenVR initialization failed.  Ensure 'Virtual Reality Supported' is checked in Player Settings, and OpenVR is added to the list of Virtual Reality SDKs.");
				return null;
			}
			OpenVR.GetGenericInterface("IVRCompositor_014", ref evrinitError);
			if (evrinitError != EVRInitError.None)
			{
				SteamVR.ReportError(evrinitError);
				SteamVR.ShutdownSystems();
				return null;
			}
			OpenVR.GetGenericInterface("IVROverlay_011", ref evrinitError);
			if (evrinitError != EVRInitError.None)
			{
				SteamVR.ReportError(evrinitError);
				SteamVR.ShutdownSystems();
				return null;
			}
		}
		catch (Exception message)
		{
			Debug.LogError(message);
			return null;
		}
		return new SteamVR();
	}

	private static void ReportError(EVRInitError error)
	{
		if (error != EVRInitError.None)
		{
			if (error != EVRInitError.Init_VRClientDLLNotFound)
			{
				if (error != EVRInitError.Driver_RuntimeOutOfDate)
				{
					if (error != EVRInitError.VendorSpecific_UnableToConnectToOculusRuntime)
					{
						Debug.Log(OpenVR.GetStringForHmdError(error));
					}
					else
					{
						Debug.Log("SteamVR Initialization Failed!  Make sure device is on, Oculus runtime is installed, and OVRService_*.exe is running.");
					}
				}
				else
				{
					Debug.Log("SteamVR Initialization Failed!  Make sure device's runtime is up to date.");
				}
			}
			else
			{
				Debug.Log("SteamVR drivers not found!  They can be installed via Steam under Library > Tools.  Visit http://steampowered.com to install Steam.");
			}
		}
	}

	public CVRSystem hmd { get; private set; }

	public CVRCompositor compositor { get; private set; }

	public CVROverlay overlay { get; private set; }

	public static bool initializing { get; private set; }

	public static bool calibrating { get; private set; }

	public static bool outOfRange { get; private set; }

	public float sceneWidth { get; private set; }

	public float sceneHeight { get; private set; }

	public float aspect { get; private set; }

	public float fieldOfView { get; private set; }

	public Vector2 tanHalfFov { get; private set; }

	public VRTextureBounds_t[] textureBounds { get; private set; }

	public SteamVR_Utils.RigidTransform[] eyes { get; private set; }

	public string hmd_TrackingSystemName
	{
		get
		{
			return this.GetStringProperty(ETrackedDeviceProperty.Prop_TrackingSystemName_String);
		}
	}

	public string hmd_ModelNumber
	{
		get
		{
			return this.GetStringProperty(ETrackedDeviceProperty.Prop_ModelNumber_String);
		}
	}

	public string hmd_SerialNumber
	{
		get
		{
			return this.GetStringProperty(ETrackedDeviceProperty.Prop_SerialNumber_String);
		}
	}

	public float hmd_SecondsFromVsyncToPhotons
	{
		get
		{
			return this.GetFloatProperty(ETrackedDeviceProperty.Prop_SecondsFromVsyncToPhotons_Float);
		}
	}

	public float hmd_DisplayFrequency
	{
		get
		{
			return this.GetFloatProperty(ETrackedDeviceProperty.Prop_DisplayFrequency_Float);
		}
	}

	public string GetTrackedDeviceString(uint deviceId)
	{
		ETrackedPropertyError etrackedPropertyError = ETrackedPropertyError.TrackedProp_Success;
		uint stringTrackedDeviceProperty = this.hmd.GetStringTrackedDeviceProperty(deviceId, ETrackedDeviceProperty.Prop_AttachedDeviceId_String, null, 0u, ref etrackedPropertyError);
		if (stringTrackedDeviceProperty > 1u)
		{
			StringBuilder stringBuilder = new StringBuilder((int)stringTrackedDeviceProperty);
			this.hmd.GetStringTrackedDeviceProperty(deviceId, ETrackedDeviceProperty.Prop_AttachedDeviceId_String, stringBuilder, stringTrackedDeviceProperty, ref etrackedPropertyError);
			return stringBuilder.ToString();
		}
		return null;
	}

	private string GetStringProperty(ETrackedDeviceProperty prop)
	{
		ETrackedPropertyError etrackedPropertyError = ETrackedPropertyError.TrackedProp_Success;
		uint stringTrackedDeviceProperty = this.hmd.GetStringTrackedDeviceProperty(0u, prop, null, 0u, ref etrackedPropertyError);
		if (stringTrackedDeviceProperty > 1u)
		{
			StringBuilder stringBuilder = new StringBuilder((int)stringTrackedDeviceProperty);
			this.hmd.GetStringTrackedDeviceProperty(0u, prop, stringBuilder, stringTrackedDeviceProperty, ref etrackedPropertyError);
			return stringBuilder.ToString();
		}
		return (etrackedPropertyError == ETrackedPropertyError.TrackedProp_Success) ? "<unknown>" : etrackedPropertyError.ToString();
	}

	private float GetFloatProperty(ETrackedDeviceProperty prop)
	{
		ETrackedPropertyError etrackedPropertyError = ETrackedPropertyError.TrackedProp_Success;
		return this.hmd.GetFloatTrackedDeviceProperty(0u, prop, ref etrackedPropertyError);
	}

	private void OnInitializing(params object[] args)
	{
		SteamVR.initializing = (bool)args[0];
	}

	private void OnCalibrating(params object[] args)
	{
		SteamVR.calibrating = (bool)args[0];
	}

	private void OnOutOfRange(params object[] args)
	{
		SteamVR.outOfRange = (bool)args[0];
	}

	private void OnDeviceConnected(params object[] args)
	{
		int num = (int)args[0];
		SteamVR.connected[num] = (bool)args[1];
	}

	private void OnNewPoses(params object[] args)
	{
		TrackedDevicePose_t[] array = (TrackedDevicePose_t[])args[0];
		this.eyes[0] = new SteamVR_Utils.RigidTransform(this.hmd.GetEyeToHeadTransform(EVREye.Eye_Left));
		this.eyes[1] = new SteamVR_Utils.RigidTransform(this.hmd.GetEyeToHeadTransform(EVREye.Eye_Right));
		for (int i = 0; i < array.Length; i++)
		{
			bool bDeviceIsConnected = array[i].bDeviceIsConnected;
			if (bDeviceIsConnected != SteamVR.connected[i])
			{
				SteamVR_Utils.Event.Send("device_connected", new object[]
				{
					i,
					bDeviceIsConnected
				});
			}
		}
		if ((long)array.Length > 0L)
		{
			ETrackingResult eTrackingResult = array[(int)((UIntPtr)0)].eTrackingResult;
			bool flag = eTrackingResult == ETrackingResult.Uninitialized;
			if (flag != SteamVR.initializing)
			{
				SteamVR_Utils.Event.Send("initializing", new object[]
				{
					flag
				});
			}
			bool flag2 = eTrackingResult == ETrackingResult.Calibrating_InProgress || eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
			if (flag2 != SteamVR.calibrating)
			{
				SteamVR_Utils.Event.Send("calibrating", new object[]
				{
					flag2
				});
			}
			bool flag3 = eTrackingResult == ETrackingResult.Running_OutOfRange || eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
			if (flag3 != SteamVR.outOfRange)
			{
				SteamVR_Utils.Event.Send("out_of_range", new object[]
				{
					flag3
				});
			}
		}
	}

	~SteamVR()
	{
		this.Dispose(false);
	}

	public void Dispose()
	{
		this.Dispose(true);
		GC.SuppressFinalize(this);
	}

	private void Dispose(bool disposing)
	{
		SteamVR_Utils.Event.Remove("initializing", new SteamVR_Utils.Event.Handler(this.OnInitializing));
		SteamVR_Utils.Event.Remove("calibrating", new SteamVR_Utils.Event.Handler(this.OnCalibrating));
		SteamVR_Utils.Event.Remove("out_of_range", new SteamVR_Utils.Event.Handler(this.OnOutOfRange));
		SteamVR_Utils.Event.Remove("device_connected", new SteamVR_Utils.Event.Handler(this.OnDeviceConnected));
		SteamVR_Utils.Event.Remove("new_poses", new SteamVR_Utils.Event.Handler(this.OnNewPoses));
		SteamVR.ShutdownSystems();
		SteamVR._instance = null;
	}

	private static void ShutdownSystems()
	{
	}

	public static void SafeDispose()
	{
		if (SteamVR._instance != null)
		{
			SteamVR._instance.Dispose();
		}
	}

	private static bool _enabled = true;

	private static SteamVR _instance;

	public static bool[] connected = new bool[16];

	public EGraphicsAPIConvention graphicsAPI;
}
