using UnityEngine;
using System.Collections;

public enum TouchState{
	Begin = 0,
	Touch = 1,
	End   = 2,
	None  = 3,
}

public struct TouchInfo{
	public int id;			
	public TouchState state;			
	public Vector2 position;
	public Vector2 previosPosition;
	public Vector3 screenPosition;
}

public class Control : MonoBehaviour {
	public Camera controlCamera;
	
	const float DEFAULT_CAMERA_HEIGHT = 12f;
	const float DEFAULT_CAMERA_NEAR =  0.2f;
	const float DEFAULT_CAMERA_FAR  = 50.0f;
	public static float cameraHeight = DEFAULT_CAMERA_HEIGHT;
	static int touchCount = 10;
	public static TouchInfo[] touches;
	public static int activeTouchCount = 0;
	public static TouchInfo[] activeTouches = new TouchInfo[10];
	public static Vector2 worldSpace = new Vector2(Screen.width, Screen.height) * (DEFAULT_CAMERA_HEIGHT / Screen.height);
	
	private static bool    useTouchControl;
	
	private static float   screenSize   = Screen.height;
	private static Vector2 screen = new Vector2(Screen.width, Screen.height);
	//for debug
	private static TouchState ctrlState = TouchState.None;
	
	void CreateCamera(float Size){
		controlCamera = gameObject.AddComponent<Camera>();
		controlCamera.nearClipPlane = DEFAULT_CAMERA_NEAR;
		controlCamera.farClipPlane  = DEFAULT_CAMERA_FAR;
		controlCamera.isOrthoGraphic = true;
		controlCamera.orthographicSize = Size;
		controlCamera.backgroundColor = Color.gray;
	}
	
	public static void RecalculateScreenAspect(float newCameraHeight){
		screenSize   = Screen.height;
		cameraHeight = newCameraHeight;
		worldSpace   = new Vector2(Screen.width, Screen.height) * (cameraHeight / Screen.height);
		screen = new Vector2(Screen.width, Screen.height);
	}
	
	void Awake(){
		controlCamera = gameObject.GetComponent<Camera>();
		if (controlCamera == null)
			CreateCamera(cameraHeight);
		else
			cameraHeight = controlCamera.orthographicSize;
		RecalculateScreenAspect(cameraHeight);
		
		touches = new TouchInfo[touchCount];
		for(int i = 0; i < touchCount; i++){
			touches[i].id = -1;
		}
		
		useTouchControl = (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer);
	}
	
	private void FindActiveTouches(){
		activeTouchCount = 0;
		for (int i = 0; i < Control.touchCount; i++){
			if (Control.touches[i].id >= 0){
				activeTouches[activeTouchCount] = Control.touches[i];
				activeTouchCount++;
				if (activeTouchCount >= 10) 
					break;
			}
		}
	}
	
	private Vector2 FindCoords(Vector2 touchPosition){
		return (cameraHeight * 2f) / screenSize * touchPosition - worldSpace;
	}
	
	private void ClearTouches(){
		for(int i = 0; i < touchCount; i++){					// очистить тачи, которые кончились в прошлом такте
			if(touches[i].state == TouchState.End){
				touches[i].id = -1;
				touches[i].state = TouchState.None;
			}
		}
	}
	
	private void AddTouch(int id, Vector2 position){
		for(int i = 0; i < touchCount; i++){					// очистить тачи, которые кончились в прошлом такте
			if(touches[i].id == -1){
				touches[i].id = id;
				touches[i].state = TouchState.Begin;
				touches[i].position = FindCoords(position);
				touches[i].screenPosition = position;
				touches[i].previosPosition = FindCoords(position);
				break;
			}
		}
	}
	
	private void UpdateTouch(int id, Vector2 position){
		for(int i = 0; i < touchCount; i++){					// очистить тачи, которые кончились в прошлом такте
			if(touches[i].id == id){
				touches[i].state = TouchState.Touch;
				touches[i].previosPosition = touches[i].position;
				touches[i].screenPosition = position;
				touches[i].position = FindCoords(position);
				break;
			}
		}
	}
	
	private void EndTouch(int id, Vector2 position){
		for(int i = 0; i < touchCount; i++){					// очистить тачи, которые кончились в прошлом такте
			if(touches[i].id == id){
				touches[i].state = TouchState.End;
				touches[i].previosPosition = touches[i].position;
				touches[i].screenPosition = position;
				touches[i].position = FindCoords(position);
				break;
			}
		}
	}
	
	void Start () {
	
	}
	
	void Update () {
		ClearTouches();
		if((useTouchControl) && (Input.touchCount > 0)){
			for(int i = 0; i < Input.touchCount; i++){	
				switch (Input.touches[i].phase){
				case TouchPhase.Began:
					AddTouch(Input.touches[i].fingerId, Input.touches[i].position);
					break;
				case TouchPhase.Moved:
				case TouchPhase.Stationary:
					UpdateTouch(Input.touches[i].fingerId, Input.touches[i].position);
					break;
				case TouchPhase.Ended:
				case TouchPhase.Canceled:
					EndTouch(Input.touches[i].fingerId, Input.touches[i].position);
					break;
				}
			}
		}
		else{
			if(Input.GetMouseButtonDown(0)) 
				AddTouch(0, Input.mousePosition);
			else 
				if(Input.GetMouseButtonUp(0)) 
					EndTouch(0, Input.mousePosition);
				else 
					if(Input.GetMouseButton(0)) 
						UpdateTouch(0, Input.mousePosition);
			
			if (Input.GetKey(KeyCode.LeftControl)){
				if (ctrlState == TouchState.Begin){
					ctrlState = TouchState.Touch;
					UpdateTouch(1, screen * 0.5f);
				}
				else
					if (ctrlState == TouchState.None){
						ctrlState = TouchState.Begin;
						AddTouch(1, screen * 0.5f);
					}
			}
			else{
				if (ctrlState == TouchState.Touch){
					ctrlState = TouchState.End;
					EndTouch(1, screen * 0.5f);
				}
				else
					if (ctrlState == TouchState.End){
						ctrlState = TouchState.None;
					}
			}
		}
		FindActiveTouches();
	}
}
