using UnityEngine;
using UnityEditor;
using System.Collections;


public class CreatePlane : ScriptableWizard
{

	public enum Orientation
	{
		Horizontal,
		Vertical
	}

	public enum AnchorPoint
	{
		TopLeft,
		TopHalf,
		TopRight,
		RightHalf,
		BottomRight,
		BottomHalf,
		BottomLeft,
		LeftHalf,
		Center
	}

	public int widthSegments = 1;
	public int lengthSegments = 1;
	public float width = 1.0f;
	public float length = 1.0f;
	public Orientation orientation = Orientation.Horizontal;
	public AnchorPoint anchor = AnchorPoint.Center;
	public bool addCollider = false;
	public bool createAtOrigin = true;
	public bool twoSided = false;
	public string optionalName;

	static Camera cam;
	static Camera lastUsedCam;


	[MenuItem("GameObject/Create Other/Custom Plane...")]
	static void CreateWizard()
	{
		cam = Camera.current;
		// Hack because camera.current doesn't return editor camera if scene view doesn't have focus
		if (!cam)
			cam = lastUsedCam;
		else
			lastUsedCam = cam;
		ScriptableWizard.DisplayWizard("Create Plane",typeof(CreatePlane));
	}


	void OnWizardUpdate()
	{
		widthSegments = Mathf.Clamp(widthSegments, 1, 254);
		lengthSegments = Mathf.Clamp(lengthSegments, 1, 254);
	}


	void OnWizardCreate()
	{
		GameObject plane = new GameObject();

		if (!string.IsNullOrEmpty(optionalName))
			plane.name = optionalName;
		else
			plane.name = "Plane";

		if (!createAtOrigin && cam)
			plane.transform.position = cam.transform.position + cam.transform.forward*5.0f;
		else
			plane.transform.position = Vector3.zero;

		Vector2 anchorOffset;
		string anchorId;
		switch (anchor)
		{
		case AnchorPoint.TopLeft:
			anchorOffset = new Vector2(-width/2.0f,length/2.0f);
			anchorId = "TL";
			break;
		case AnchorPoint.TopHalf:
			anchorOffset = new Vector2(0.0f,length/2.0f);
			anchorId = "TH";
			break;
		case AnchorPoint.TopRight:
			anchorOffset = new Vector2(width/2.0f,length/2.0f);
			anchorId = "TR";
			break;
		case AnchorPoint.RightHalf:
			anchorOffset = new Vector2(width/2.0f,0.0f);
			anchorId = "RH";
			break;
		case AnchorPoint.BottomRight:
			anchorOffset = new Vector2(width/2.0f,-length/2.0f);
			anchorId = "BR";
			break;
		case AnchorPoint.BottomHalf:
			anchorOffset = new Vector2(0.0f,-length/2.0f);
			anchorId = "BH";
			break;
		case AnchorPoint.BottomLeft:
			anchorOffset = new Vector2(-width/2.0f,-length/2.0f);
			anchorId = "BL";
			break;			
		case AnchorPoint.LeftHalf:
			anchorOffset = new Vector2(-width/2.0f,0.0f);
			anchorId = "LH";
			break;			
		case AnchorPoint.Center:
		default:
			anchorOffset = Vector2.zero;
			anchorId = "C";
			break;
		}

		MeshFilter meshFilter = (MeshFilter)plane.AddComponent(typeof(MeshFilter));
		plane.AddComponent(typeof(MeshRenderer));

		string planeAssetName = plane.name + widthSegments + "x" + lengthSegments + "W" + width + "L" + length + (orientation == Orientation.Horizontal? "H" : "V") + anchorId + ".asset";
		Mesh m = (Mesh)AssetDatabase.LoadAssetAtPath("Assets/Editor/" + planeAssetName,typeof(Mesh));

		if (m == null)
		{
			m = new Mesh();
			m.name = plane.name;

			int hCount2 = widthSegments+1;
			int vCount2 = lengthSegments+1;
			int numTriangles = widthSegments * lengthSegments * 6;
			if (twoSided) {
				numTriangles *= 2;
			}
			int numVertices = hCount2 * vCount2;

			Vector3[] vertices = new Vector3[numVertices];
			Vector2[] uvs = new Vector2[numVertices];
			int[] triangles = new int[numTriangles];
			Vector4[] tangents = new Vector4[numVertices];
			Vector4 tangent = new Vector4(1f, 0f, 0f, -1f);

			int index = 0;
			float uvFactorX = 1.0f/widthSegments;
			float uvFactorY = 1.0f/lengthSegments;
			float scaleX = width/widthSegments;
			float scaleY = length/lengthSegments;
			for (float y = 0.0f; y < vCount2; y++)
			{
				for (float x = 0.0f; x < hCount2; x++)
				{
					if (orientation == Orientation.Horizontal)
					{
						vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, 0.0f, y*scaleY - length/2f - anchorOffset.y);
					}
					else
					{
						vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, y*scaleY - length/2f - anchorOffset.y, 0.0f);
					}
					tangents[index] = tangent;
					uvs[index++] = new Vector2(x*uvFactorX, y*uvFactorY);
				}
			}

			index = 0;
			for (int y = 0; y < lengthSegments; y++)
			{
				for (int x = 0; x < widthSegments; x++)
				{
					triangles[index]   = (y     * hCount2) + x;
					triangles[index+1] = ((y+1) * hCount2) + x;
					triangles[index+2] = (y     * hCount2) + x + 1;

					triangles[index+3] = ((y+1) * hCount2) + x;
					triangles[index+4] = ((y+1) * hCount2) + x + 1;
					triangles[index+5] = (y     * hCount2) + x + 1;
					index += 6;
				}
				if (twoSided) {
					// Same tri vertices with order reversed, so normals point in the opposite direction
					for (int x = 0; x < widthSegments; x++)
					{
						triangles[index]   = (y     * hCount2) + x;
						triangles[index+1] = (y     * hCount2) + x + 1;
						triangles[index+2] = ((y+1) * hCount2) + x;

						triangles[index+3] = ((y+1) * hCount2) + x;
						triangles[index+4] = (y     * hCount2) + x + 1;
						triangles[index+5] = ((y+1) * hCount2) + x + 1;
						index += 6;
					}
				}
			}

			m.vertices = vertices;
			m.uv = uvs;
			m.triangles = triangles;
			m.tangents = tangents;
			m.RecalculateNormals();

			AssetDatabase.CreateAsset(m, "Assets/" + planeAssetName);
			AssetDatabase.SaveAssets();
		}

		meshFilter.sharedMesh = m;
		m.RecalculateBounds();

		if (addCollider)
			plane.AddComponent(typeof(BoxCollider));

		Selection.activeObject = plane;
	}
}