using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;

public class PlanetarSpaceState : SpaceStateController
{
	static PlanetarSpaceState instance = null;

	[SerializeField] Camera playerCamera = null; // Set from editor - main camera for mouse raytrace
	[SerializeField] Light sun = null; // Set from editor

	StarMap.SpaceObject currentPlanet = null;
	PlanetarMesh planetarMesh = null;
	SphereCollider planetarSphere = null;
	List<InterestPointController> pointsOfInterest = new List<InterestPointController>();
	bool dropSensorMode = false;

	const float sizeMultiplier = 10f;

	public static bool DropSensorMode {
		get {
			if (instance == null) return false;
			return instance.dropSensorMode;
		}
		set {
			if (instance != null)
			{
				instance.dropSensorMode = value;
			}
		}
	}

	public override void OnStateShow (bool fromBigger)
	{
		DropSensorMode = false;
		CameraController.SetPosition(Vector3.zero, false);
		
		if (currentPlanet != StarMap.Stars [Player.info.StarId].objects[Player.info.currentObjectId])
		{
			currentPlanet = StarMap.Stars [Player.info.StarId].objects[Player.info.currentObjectId];
			RegeneratePlanet (currentPlanet);
			cameraMinYAngle = -90f;
			cameraMaxYAngle = 90f;
			minCameraDistance = currentPlanet.size * sizeMultiplier + 2f;
			maxCameraDistance = currentPlanet.size * sizeMultiplier + 15f;
		}
		float distance = minCameraDistance;
		if (fromBigger)
		{
			distance = maxCameraDistance + 5f;
		}
		CameraController.SetNeedDistance (minCameraDistance + 6f);
		CameraController.SetBorders (distance, minCameraDistance, maxCameraDistance, cameraMinYAngle, cameraMaxYAngle);
	}

	static Color From32(Color32 color)
	{
		return new Color (
			(float)color.r / 255f,
			(float)color.g / 255f,
			(float)color.b / 255f);
	}

	public void RegeneratePlanet(StarMap.SpaceObject planet)
	{
		if (planetarMesh != null)
		{
			Destroy(planetarMesh.gameObject);
		}
		GameObject planetarObject = new GameObject (planet.name);
		planetarObject.transform.parent = transform;
		planetarMesh = planetarObject.AddComponent<PlanetarMesh>();
		GradientColorKey[] colorKeys = new GradientColorKey[planet.colorKeys.Length];
		for (int i = 0; i < planet.colorKeys.Length; i++)
		{
			colorKeys[i] = new GradientColorKey(From32(planet.colorKeys[i]), (float)i / (float)planet.colorKeys.Length);
		}
		planetarMesh.groundColor.SetKeys (colorKeys, planetarMesh.groundColor.alphaKeys);
		planetarMesh.radius = planet.size * sizeMultiplier;
		planetarMesh.textureSize = 512;
		planetarMesh.details = 18;
		planetarMesh.isGasGiant = (planet.type == SpaceObjectType.gasGiant);
		planetarMesh.transform.localEulerAngles = new Vector3 (0, planet.angle, 0);
		planetarSphere = planetarMesh.gameObject.AddComponent<SphereCollider>();
		planetarSphere.radius = planetarMesh.radius;
		if (sun != null)
		{
			sun.transform.localEulerAngles = new Vector3 (0, planet.angle + 90, 0);
		}
		pointsOfInterest.ForEach ((point) => {
			if (point) Destroy(point.gameObject);
		});
		pointsOfInterest.Clear();
		// Generate points of interest
		if (currentPlanet.points != null)
		{
			//scannerPower
			for (int i = 0; i < currentPlanet.points.Length; i++) {
				pointsOfInterest.Add(InterestPointController.Create(transform, currentPlanet.points[i]));
			}
		}
	}

	void Start()
	{
		instance = this;
	}

	void SelectPoint(int pointId)
	{
		if (Player.IsPointVisited (pointId))
		{
			return;
		}
		DropShuttle (pointId);
	}

	void DropShuttle(int pointId)
	{
		Player.VisitPoint (pointId);
		pointsOfInterest [pointId].Collect ();
		// Discover nearest(to shuttle) drop points
		float ShuttleScanRange = 0.2f;
		ScanRange (currentPlanet.points[pointId].position, ShuttleScanRange);
	}

	void DropSensor(Vector3 position)
	{
		float sensorScanRange = 0.3f;
		// TODO check sensors consumption
		Logic.triggers [Res.dropScanner] -= 1;
		ScanRange (position * (1f / sizeMultiplier), sensorScanRange);
		dropSensorMode = false;
	}

	void ScanRange(Vector3 position, float scanRange)
	{
		for (int i = 0; i < currentPlanet.points.Length; i++)
		{
			if ((currentPlanet.points[i].position - position).magnitude <= scanRange && !Player.IsPointVisited(i))
			{
				Player.DiscoverPoint(i);
				pointsOfInterest[i].UpdateState();
			}
		}
	}

	void Update ()
	{
		TracePlayerTouch ();
	}
	
	void TracePlayerTouch()
	{
		if (playerCamera == null)
		{
			Debug.LogError("PlanetarSpaceState " + name + " does not set player camera");
			return;
		}
		if (!EventSystem.current.IsPointerOverGameObject ())
		{
			if (Input.GetMouseButtonUp (0))
			{
				RaycastHit hitInfo;
				if (Physics.Raycast (playerCamera.ScreenPointToRay (Input.mousePosition), out hitInfo, 50f))
				{
					if (hitInfo.collider != null)
					{
						if (dropSensorMode)
						{ // drop bot - all planet sphere
							if ( hitInfo.collider == planetarSphere)
							{
								DropSensor(hitInfo.point);
							}
						}
						else
						{ // else points
							for (int i = 0; i < pointsOfInterest.Count; i++)
							{
								if (pointsOfInterest[i] != null &&  hitInfo.collider == pointsOfInterest[i].selfCollider)
								{
									SelectPoint (i);
									break;
								}
							}
						}
					}
				}
			}
		}
	}
}
