using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[RequireComponent (typeof (MeshFilter))]
[RequireComponent (typeof (MeshRenderer))]
public class MonotypeText : MonoBehaviour {

	[SerializeField] private Material material;
	[SerializeField] string textValue = "";
	[SerializeField] private Vector2 pivot = new Vector2(0.0f, 0.5f);		
	[SerializeField] private Vector2 spriteScale = new Vector2(0.6f, 0.6f);
	Color color;
	
	protected MeshFilter meshFilter;						
	protected MeshRenderer meshRenderer;	
	
	bool created = false;					
	
	protected bool visibility = true;
	
	public bool visible {
        get {
            return visibility;
        }
        set {
			if (visibility != value) {
				SetVisible(value);
			}
        }
    }
	
	public string text {
		get {
			return textValue;
		}
		set {
			SetText(value);
		}
	}
	
	private void SetVisible(bool value){
		if(visibility != value && meshRenderer != null){
			visibility = value;								
			meshRenderer.enabled = value;
		}
	}
	
	private void SetText(string value){
		textValue = value;
		if(meshFilter != null){			
			meshFilter.sharedMesh = CreateMesh(spriteScale, pivot, textValue);
		}
	}
	
	public void SetMaterial(Material newMaterial){
		material = newMaterial;
		if (created){
			meshRenderer.material = material;
		}
	}	
	
	public void SetColor(Color newColor){
		color = newColor;
		if (created){
			meshRenderer.material.color = color;
		}
	}
	
	void Awake () {
		meshRenderer = gameObject.GetComponent<MeshRenderer>();
		if (meshRenderer == null)
			meshRenderer = gameObject.AddComponent<MeshRenderer>();
		meshFilter = gameObject.GetComponent<MeshFilter>();
		if (meshFilter == null)
			meshFilter = gameObject.AddComponent<MeshFilter>();
	}
	
	public void SetPivot(Vector2 anchor){
		pivot = anchor;
		if (created){
			meshFilter.mesh = CreateMesh(spriteScale, pivot, textValue);
		}
	}
	 
	public void SetPivot(float x, float y){
		SetPivot(new Vector2(x,y));
	}
	
	void Start () {
		if (material == null)
			material = new Material(Shader.Find("Unlit/Transparent"));
		meshRenderer.material = material;
		meshFilter.sharedMesh = CreateMesh(spriteScale, pivot, textValue);
		created = true;
	}
	
	const string symbols = " 0123456789.,:;!?@%$#()+-=/\\*abcdefghijklmnopqrstuvwxyzабвгдежзийклмнопрстуфхцчшщыьъэюя";
	int[] codes = {	-1,0,1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
		42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
		84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118
	};
	
	const float SYMBOL_WIDTH  = 1f / 256f * 6f;
	const float SYMBOL_HEIGHT = 1f / 256f * 6f;
	
	Mesh CreateMesh(Vector2 scale, Vector2 pivot, string text ){
//		Rect textureCoords = new Rect(0,0,1,1);
		int[] charCodes = new int[text.Length];
		int realChars = 0;
		for (int i = 0; i < text.Length; i++){
			charCodes[i] = -1;
			for(int j = 0; j < symbols.Length; j++) {
				if (text[i] == symbols[j]){
					charCodes[i] = codes[j];
					if (charCodes[i] >= 0)
						realChars ++;
					break;
				}
			}
		}
		Vector3[] vertices = new Vector3[realChars * 4]; 
		Vector2[] uv = new Vector2[realChars * 4];
		int[] triangles = new int[realChars * 6];
		int z = 0;
		for(int i = 0; i < charCodes.Length; i++){
			if (charCodes[i] >= 0){
				int u = charCodes[i] % 42;
				int v = charCodes[i] / 42;
				vertices[z * 4 + 0] = new Vector3(i * scale.x			- pivot.x * scale.x * charCodes.Length,        0 - pivot.y * scale.y , 0);
				vertices[z * 4 + 1] = new Vector3(i * scale.x			- pivot.x * scale.x * charCodes.Length,  scale.y - pivot.y * scale.y , 0);
				vertices[z * 4 + 2] = new Vector3(i * scale.x + scale.x	- pivot.x * scale.x * charCodes.Length,  scale.y - pivot.y * scale.y , 0);
				vertices[z * 4 + 3] = new Vector3(i * scale.x + scale.x	- pivot.x * scale.x * charCodes.Length,        0 - pivot.y * scale.y , 0);
				uv[z * 4 + 0] = new Vector3(u * SYMBOL_WIDTH				, v * SYMBOL_HEIGHT, 0);
				uv[z * 4 + 1] = new Vector3(u * SYMBOL_WIDTH				, v * SYMBOL_HEIGHT + SYMBOL_HEIGHT, 0);
				uv[z * 4 + 2] = new Vector3(u * SYMBOL_WIDTH + SYMBOL_WIDTH	, v * SYMBOL_HEIGHT + SYMBOL_HEIGHT, 0);
				uv[z * 4 + 3] = new Vector3(u * SYMBOL_WIDTH + SYMBOL_WIDTH	, v * SYMBOL_HEIGHT, 0);
				triangles[z * 6 + 0] = z * 4 + 0;
				triangles[z * 6 + 1] = z * 4 + 1;
				triangles[z * 6 + 2] = z * 4 + 2;
				triangles[z * 6 + 3] = z * 4 + 0;
				triangles[z * 6 + 4] = z * 4 + 2;
				triangles[z * 6 + 5] = z * 4 + 3;
				z++;
			}
		}
		
		return new Mesh { vertices = vertices, uv = uv, triangles = triangles };
	}
	
	#if UNITY_EDITOR		
	string previosText = "";
	Vector2 prevPivot = new Vector2(0.0f, 0.5f);
    void OnDrawGizmos() {
		bool needChange = false;
		if (previosText != textValue){
			previosText = textValue;
			needChange = true;
		}
		if (prevPivot != pivot){
			prevPivot = pivot;
			needChange = true;
		}
		if (needChange) {
			meshFilter.sharedMesh = CreateMesh(spriteScale, pivot, textValue);
			Resources.UnloadUnusedAssets();
		}
    }	
	#endif
	
	void Update () {	
		
	}
}
