using UnityEngine;

namespace UnityEditor.ProGrids
{
	[System.Flags]
	enum Axis {
		None = 0x0,
		X = 0x1,
		Y = 0x2,
		Z = 0x4,
		NegX = 0x8,
		NegY = 0x16,
		NegZ = 0x32
	}

	enum SnapUnit {
		Meter,
		Centimeter,
		Millimeter,
		Inch,
		Foot,
		Yard,
		Parsec
	}

	enum SnapMethod
	{
		SnapOnSelectedAxis,
		SnapOnAllAxes
	}

	static class EnumExtension
	{
		/// <summary>
		/// Multiplies a Vector3 using the inverse value of an axis (eg, Axis.Y becomes Vector3(1, 0, 1) )
		/// </summary>
		/// <param name="v"></param>
		/// <param name="axis"></param>
		/// <returns></returns>
		internal static Vector3 InverseAxisMask(Vector3 v, Axis axis)
		{
			switch(axis)
			{
				case Axis.X:
				case Axis.NegX:
					return Vector3.Scale(v, new Vector3(0f, 1f, 1f));

				case Axis.Y:
				case Axis.NegY:
					return Vector3.Scale(v, new Vector3(1f, 0f, 1f));

				case Axis.Z:
				case Axis.NegZ:
					return Vector3.Scale(v, new Vector3(1f, 1f, 0f));

				default:
					return v;
			}
		}

		internal static Vector3 AxisMask(Vector3 v, Axis axis)
		{
			switch(axis)
			{
				case Axis.X:
				case Axis.NegX:
					return Vector3.Scale(v, new Vector3(1f, 0f, 0f));

				case Axis.Y:
				case Axis.NegY:
					return Vector3.Scale(v, new Vector3(0f, 1f, 0f));

				case Axis.Z:
				case Axis.NegZ:
					return Vector3.Scale(v, new Vector3(0f, 0f, 1f));

				default:
					return v;
			}
		}

		internal static float SnapUnitValue(SnapUnit su)
		{
			switch(su)
			{
				case SnapUnit.Meter:
					return Defaults.Meter;
				case SnapUnit.Centimeter:
					return Defaults.Centimeter;
				case SnapUnit.Millimeter:
					return Defaults.Millimeter;
				case SnapUnit.Inch:
					return Defaults.Inch;
				case SnapUnit.Foot:
					return Defaults.Foot;
				case SnapUnit.Yard:
					return Defaults.Yard;
				case SnapUnit.Parsec:
					return Defaults.Parsec;
				default:
					return Defaults.Meter;
			}
		}

		internal static SnapUnit SnapUnitWithString(string str)
		{
			foreach (SnapUnit su in SnapUnit.GetValues(typeof(SnapUnit)))
			{
				if (su.ToString() == str)
					return su;
			}
			return (SnapUnit)0;
		}

		internal static Axis AxisWithVector(Vector3 val)
		{
			Vector3 v = new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z));

			if (v.x > v.y && v.x > v.z)
			{
				if (val.x > 0)
					return Axis.X;
				else
					return Axis.NegX;
			}
			else
			if (v.y > v.x && v.y > v.z)
			{
				if (val.y > 0)
					return Axis.Y;
				else
					return Axis.NegY;
			}
			else
			{
				if (val.z > 0)
					return Axis.Z;
				else
					return Axis.NegZ;
			}
		}

		internal static Vector3 VectorWithAxis(Axis axis)
		{
			switch (axis)
			{
				case Axis.X:
					return Vector3.right;
				case Axis.Y:
					return Vector3.up;
				case Axis.Z:
					return Vector3.forward;
				case Axis.NegX:
					return -Vector3.right;
				case Axis.NegY:
					return -Vector3.up;
				case Axis.NegZ:
					return -Vector3.forward;

				default:
					return Vector3.forward;
			}
		}
	}
}
