﻿using UnityEngine;
using System.Collections;
using Leap;

public class LeapMouse : MonoBehaviour {
	public static Vector2 position {
		get {
			if (Instance != null) {
				if (Instance.UseMouseClone) {
					return Input.mousePosition;
				} else {
					return Instance.mousePosition;
				}
			}
			return Vector2.one * float.MaxValue;
		}

		set { 
			if (Instance != null)
				Instance.mousePosition = value;
		}
	}
	Vector2 mousePosition = Vector2.one * -99999f;

	public static Vector3 value {
		get {
			if (Instance != null) {
				return Instance.leapValue;
			}

			return Vector3.zero;
		}
	}
	Vector3 leapValue = Vector3.zero;

	public static Vector3 rotValue {
		get {
			if (Instance != null) {
				return Instance.leapRotValue;
			}

			return Vector3.zero;
		}
	}
	Vector3 leapRotValue = Vector3.zero;

	public static LeapMouse Instance {
		get {
			if (instance == null) {
				instance = FindObjectOfType<LeapMouse> ();
			}

			return instance;
		}
	}

	static LeapMouse instance = null;

	static Rect Bound = new Rect (-98, 135, 148, 143);
	static float Near = -150f;
	static float Far = 150f;
	public static void SetBound (float left, float top, float width, float height) {
		PlayerPrefs.SetFloat ("left", left);
		PlayerPrefs.SetFloat ("top", top);
		PlayerPrefs.SetFloat ("width", width);
		PlayerPrefs.SetFloat ("height", height);

		Bound.Set (left, top, width, height);
	}

	public Transform BottomLeft;
	public Transform TopRight;
	public UISprite widget;
	bool useMouseClone = true;
	public bool UseMouseClone {
		get {
			return useMouseClone && !connected;
		}

		set {
			useMouseClone = value;
		}
	} 

	void Awake () {
		UnityVectorExtension.InputScale = Vector3.one;

		float left = PlayerPrefs.GetFloat ("left", -100f);
		float top = PlayerPrefs.GetFloat ("top", 135f);
		float width = PlayerPrefs.GetFloat ("width", 150f);
		float height = PlayerPrefs.GetFloat ("height", 150f);

		SetBound (left, top, width, height);

		LeapInterface.HandEvent += HandEvent;
		LeapInterface.LostEvent += HandLost;
	}

	void OnDestroy () {
		instance = null;
		LeapInterface.HandEvent -= HandEvent;
		LeapInterface.LostEvent -= HandLost;
	}

	public void SetFillByHover (float fillPercent) {
		widget.fillAmount = fillPercent;
	}

	bool connected = false;
	void HandEvent (Hand h) {
		connected = true;

		Vector3 pos = UnityVectorExtension.ToUnity (h.StabilizedPalmPosition);
		pos.x = Mathf.Clamp (pos.x, Bound.xMin, Bound.xMax);
		pos.y = Mathf.Clamp (pos.y, Bound.yMin, Bound.yMax);
		pos.z = Mathf.Clamp (pos.z, Near, Far);

		pos -= new Vector3 (Bound.xMin, Bound.yMin, Near);

		pos.x = pos.x / Bound.width;
		pos.y = pos.y / Bound.height;
		pos.z = pos.z / (Far - Near);

		Set (pos);

		float pitch = h.Direction.Pitch * Mathf.Rad2Deg;
		float yaw = h.Direction.Yaw * Mathf.Rad2Deg;
		float roll = h.PalmNormal.Roll * Mathf.Rad2Deg;

		if (pitch > 180f) pitch -= 360f;
		if (yaw > 180f) yaw -= 360f;
		if (roll > 180f) roll -= 360f;

		Set (pitch, yaw, roll);
	}

	void HandLost () {
		connected = false;
	}

	void Set (Vector3 pos) {

		Vector3 screenSize = new Vector3 (UnityEngine.Screen.width, UnityEngine.Screen.height);
		mousePosition = Vector3.Scale (pos, screenSize);

		pos -= Vector3.one * 0.5f;
		leapValue = pos;

		Vector3 ratioNGUIScreen = TopRight.localPosition - BottomLeft.localPosition;
		transform.localPosition = Vector3.Scale (ratioNGUIScreen, pos);
	}

	void Set (float pitch, float yaw, float roll) {
		leapRotValue = new Vector3 (pitch, yaw, roll);
	}

	void Update () {
		if (Input.GetKeyDown (KeyCode.P)) {
			useMouseClone = !useMouseClone;
		}

		UnityEngine.Screen.showCursor = !UseMouseClone;
		if (UseMouseClone) {
			var _leapvalue = Vector3.Scale (Input.mousePosition, new Vector3(1f/UnityEngine.Screen.width, 1f/UnityEngine.Screen.height));

			if (Input.GetKey (KeyCode.Space)) {
				_leapvalue.z = 1f;
			} else if (Input.GetKey (KeyCode.LeftShift)) {
				_leapvalue.z = 0f;
			}else {
				_leapvalue.z = 0.5f;
			}

			Set (_leapvalue);

			var _leapRotValue = leapRotValue;
			if (Input.GetKey (KeyCode.A)) {
				_leapRotValue.z = -30f;
			}
			if (Input.GetKey (KeyCode.D)) {
				_leapRotValue.z = 30f;
			}

			Set (_leapRotValue.x, _leapRotValue.y, _leapRotValue.z);
		}

		LeapInput.Update ();
	}
}
