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

namespace Leap
{
	public class TestHandFactory
	{
		public static Frame MakeTestFrame(int frameId, bool leftHandIncluded, bool rightHandIncluded)
		{
			Frame frame = new Frame((long)frameId, 0L, 120f, default(InteractionBox), new List<Hand>());
			if (leftHandIncluded)
			{
				frame.Hands.Add(TestHandFactory.MakeTestHand(frameId, 10, true));
			}
			if (rightHandIncluded)
			{
				frame.Hands.Add(TestHandFactory.MakeTestHand(frameId, 20, false));
			}
			return frame;
		}

		public static Hand MakeTestHand(int frameId, int handId, bool isLeft)
		{
			List<Finger> list = new List<Finger>(5);
			list.Add(TestHandFactory.MakeThumb(frameId, handId, isLeft));
			list.Add(TestHandFactory.MakeIndexFinger(frameId, handId, isLeft));
			list.Add(TestHandFactory.MakeMiddleFinger(frameId, handId, isLeft));
			list.Add(TestHandFactory.MakeRingFinger(frameId, handId, isLeft));
			list.Add(TestHandFactory.MakePinky(frameId, handId, isLeft));
			Vector vector = new Vector(-7.05809927f, 4f, 50f);
			Vector vector2 = vector + 250f * Vector.Backward;
			Arm arm = new Arm(vector2, vector, (vector2 + vector) / 2f, Vector.Forward, 250f, 41f, LeapQuaternion.Identity);
			Hand hand = new Hand((long)frameId, handId, 1f, 0f, 0f, 0f, 0f, 85f, isLeft, 0f, arm, list, new Vector(0f, 0f, 0f), new Vector(0f, 0f, 0f), new Vector(0f, 0f, 0f), Vector.Down, Vector.Forward, new Vector(-4.36385775f, 6.5f, 31.0111351f));
			LeapTransform identity = LeapTransform.Identity;
			identity.rotation = TestHandFactory.AngleAxis(3.14159274f, Vector.Forward);
			if (isLeft)
			{
				identity.translation = new Vector(80f, 120f, 0f);
			}
			else
			{
				identity.translation = new Vector(-80f, 120f, 0f);
				identity.MirrorX();
			}
			return hand.TransformedCopy(identity);
		}

		private static LeapQuaternion AngleAxis(float angle, Vector axis)
		{
			if (!axis.MagnitudeSquared.NearlyEquals(1f, 1.1920929E-07f))
			{
				throw new ArgumentException("Axis must be a unit vector.");
			}
			float num = Mathf.Sin(angle / 2f);
			LeapQuaternion leapQuaternion = new LeapQuaternion(num * axis.x, num * axis.y, num * axis.z, Mathf.Cos(angle / 2f));
			return leapQuaternion.Normalized;
		}

		private static LeapQuaternion RotationBetween(Vector fromDirection, Vector toDirection)
		{
			float num = Mathf.Sqrt(2f + 2f * fromDirection.Dot(toDirection));
			Vector vector = 1f / num * fromDirection.Cross(toDirection);
			return new LeapQuaternion(vector.x, vector.y, vector.z, 0.5f * num);
		}

		private static Finger MakeThumb(int frameId, int handId, bool isLeft)
		{
			Vector position = new Vector(19.33826f, -6f, 53.1684837f);
			Vector forward = new Vector(0.6363291f, -0.5f, -0.8997871f);
			Vector up = new Vector(0.804793954f, 0.447213918f, 0.390264541f);
			float[] jointLengths = new float[]
			{
				0f,
				46.22f,
				31.57f,
				21.67f
			};
			return TestHandFactory.MakeFinger(Finger.FingerType.TYPE_THUMB, position, forward, up, jointLengths, frameId, handId, handId, isLeft);
		}

		private static Finger MakeIndexFinger(int frameId, int handId, bool isLeft)
		{
			Vector position = new Vector(23.1812859f, 2f, -23.1493454f);
			Vector forward = new Vector(0.16604431f, -0.148340449f, -0.974897146f);
			Vector up = new Vector(0.0249066465f, 0.988936365f, -0.146234572f);
			float[] jointLengths = new float[]
			{
				68.12f,
				39.78f,
				22.38f,
				15.82f
			};
			return TestHandFactory.MakeFinger(Finger.FingerType.TYPE_INDEX, position, forward, up, jointLengths, frameId, handId, handId + 1, isLeft);
		}

		private static Finger MakeMiddleFinger(int frameId, int handId, bool isLeft)
		{
			Vector position = new Vector(2.78877831f, 4f, -23.2521057f);
			Vector forward = new Vector(0.0295207854f, -0.148340449f, -0.988495648f);
			Vector up = new Vector(-0.145765275f, 0.977715969f, -0.151075974f);
			float[] jointLengths = new float[]
			{
				64.6f,
				44.63f,
				26.33f,
				17.4f
			};
			return TestHandFactory.MakeFinger(Finger.FingerType.TYPE_MIDDLE, position, forward, up, jointLengths, frameId, handId, handId + 2, isLeft);
		}

		private static Finger MakeRingFinger(int frameId, int handId, bool isLeft)
		{
			Vector position = new Vector(-17.4471684f, 4f, -17.2791443f);
			Vector forward = new Vector(-0.121317938f, -0.148340344f, -0.9814668f);
			Vector up = new Vector(-0.216910467f, 0.968834937f, -0.1196191f);
			float[] jointLengths = new float[]
			{
				58f,
				41.37f,
				25.65f,
				17.3f
			};
			return TestHandFactory.MakeFinger(Finger.FingerType.TYPE_RING, position, forward, up, jointLengths, frameId, handId, handId + 3, isLeft);
		}

		private static Finger MakePinky(int frameId, int handId, bool isLeft)
		{
			Vector position = new Vector(-35.33744f, 0f, -9.728714f);
			Vector forward = new Vector(-0.259328932f, -0.105851226f, -0.959970832f);
			Vector up = new Vector(-0.353350222f, 0.9354595f, -0.007693566f);
			float[] jointLengths = new float[]
			{
				53.69f,
				32.74f,
				18.11f,
				15.96f
			};
			return TestHandFactory.MakeFinger(Finger.FingerType.TYPE_PINKY, position, forward, up, jointLengths, frameId, handId, handId + 4, isLeft);
		}

		private static Finger MakeFinger(Finger.FingerType name, Vector position, Vector forward, Vector up, float[] jointLengths, int frameId, int handId, int fingerId, bool isLeft)
		{
			forward = forward.Normalized;
			up = up.Normalized;
			Bone[] array = new Bone[5];
			float num = -jointLengths[0];
			Bone bone = TestHandFactory.MakeBone(Bone.BoneType.TYPE_METACARPAL, position + forward * num, jointLengths[0], 8f, forward, up, isLeft);
			num += jointLengths[0];
			array[0] = bone;
			Bone bone2 = TestHandFactory.MakeBone(Bone.BoneType.TYPE_PROXIMAL, position + forward * num, jointLengths[1], 8f, forward, up, isLeft);
			num += jointLengths[1];
			array[1] = bone2;
			Bone bone3 = TestHandFactory.MakeBone(Bone.BoneType.TYPE_INTERMEDIATE, position + forward * num, jointLengths[2], 8f, forward, up, isLeft);
			num += jointLengths[2];
			array[2] = bone3;
			Bone bone4 = TestHandFactory.MakeBone(Bone.BoneType.TYPE_DISTAL, position + forward * num, jointLengths[3], 8f, forward, up, isLeft);
			array[3] = bone4;
			return new Finger((long)frameId, handId, fingerId, 0f, position, new Vector(0f, 0f, 0f), forward, position, 8f, jointLengths[1] + jointLengths[2] + jointLengths[3], true, name, array[0], array[1], array[2], array[3]);
		}

		private static Bone MakeBone(Bone.BoneType name, Vector proximalPosition, float length, float width, Vector direction, Vector up, bool isLeft)
		{
			LeapQuaternion rotation = Quaternion.LookRotation(-direction.ToVector3(), up.ToVector3()).ToLeapQuaternion();
			return new Bone(proximalPosition, proximalPosition + direction * length, Vector.Lerp(proximalPosition, proximalPosition + direction * length, 0.5f), direction, length, width, name, rotation);
		}
	}
}
