using System;
using System.Collections;
using Leap.Unity.Attributes;
using UnityEngine;

namespace Leap.Unity
{
	public class FingerDirectionDetector : Detector
	{
		private void OnValidate()
		{
			if (this.OffAngle < this.OnAngle)
			{
				this.OffAngle = this.OnAngle;
			}
		}

		private void Awake()
		{
			this.watcherCoroutine = this.fingerPointingWatcher();
		}

		private void OnEnable()
		{
			base.StartCoroutine(this.watcherCoroutine);
		}

		private void OnDisable()
		{
			base.StopCoroutine(this.watcherCoroutine);
			this.Deactivate();
		}

		private IEnumerator fingerPointingWatcher()
		{
			int selectedFinger = this.selectedFingerOrdinal();
			for (;;)
			{
				if (this.HandModel != null)
				{
					Hand hand = this.HandModel.GetLeapHand();
					if (hand != null)
					{
						Vector3 targetDirection = this.selectedDirection(hand.Fingers[selectedFinger].TipPosition.ToVector3());
						Vector3 fingerDirection = hand.Fingers[selectedFinger].Bone(Bone.BoneType.TYPE_DISTAL).Direction.ToVector3();
						float num = Vector3.Angle(fingerDirection, targetDirection);
						if (this.HandModel.IsTracked && num <= this.OnAngle)
						{
							this.Activate();
						}
						else if (!this.HandModel.IsTracked || num >= this.OffAngle)
						{
							this.Deactivate();
						}
					}
				}
				yield return new WaitForSeconds(this.Period);
			}
			yield break;
		}

		private Vector3 selectedDirection(Vector3 tipPosition)
		{
			switch (this.PointingType)
			{
			case PointingType.RelativeToCamera:
				return Camera.main.transform.TransformDirection(this.PointingDirection);
			case PointingType.RelativeToHorizon:
			{
				float y = Camera.main.transform.rotation.eulerAngles.y;
				Quaternion rotation = Quaternion.AngleAxis(y, Vector3.up);
				return rotation * this.PointingDirection;
			}
			case PointingType.RelativeToWorld:
				return this.PointingDirection;
			case PointingType.AtTarget:
				return this.TargetObject.position - tipPosition;
			default:
				return this.PointingDirection;
			}
		}

		private int selectedFingerOrdinal()
		{
			switch (this.FingerName)
			{
			case Finger.FingerType.TYPE_THUMB:
				return 0;
			case Finger.FingerType.TYPE_INDEX:
				return 1;
			case Finger.FingerType.TYPE_MIDDLE:
				return 2;
			case Finger.FingerType.TYPE_RING:
				return 3;
			case Finger.FingerType.TYPE_PINKY:
				return 4;
			default:
				return 1;
			}
		}

		[Tooltip("The interval in seconds at which to check this detector's conditions.")]
		public float Period = 0.1f;

		[AutoFind(AutoFindLocations.Parents)]
		[Tooltip("The hand model to watch. Set automatically if detector is on a hand.")]
		public IHandModel HandModel;

		[Tooltip("The finger to observe.")]
		public Finger.FingerType FingerName = Finger.FingerType.TYPE_INDEX;

		[Tooltip("The target direction.")]
		public Vector3 PointingDirection = Vector3.forward;

		[Tooltip("How to treat the target direction.")]
		public PointingType PointingType = PointingType.RelativeToHorizon;

		[Tooltip("A target object(optional). Use PointingType.AtTarget")]
		public Transform TargetObject;

		[Tooltip("The angle in degrees from the target direction at which to turn on.")]
		[Range(0f, 360f)]
		public float OnAngle = 15f;

		[Tooltip("The angle in degrees from the target direction at which to turn off.")]
		[Range(0f, 360f)]
		public float OffAngle = 25f;

		private IEnumerator watcherCoroutine;
	}
}
