using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LevelController: MonoBehaviour {
	public GameObject Origin;
    public GameObject Target;
    public Transform UnitPrefab;
    public Transform TowerPrefab;
	public Text ScrapMetalValue;
	public Text TimeValue;
	public AudioClip invalidBuildingPlacement;
	public AudioClip buildingPlaced;

    public List<TowerController> Towers;
	public List<ObjectBaseController> Objects;

	public Transform buildObject;
	public float scrapMetal = 0;
	public float timeToGenerateScrapMetal = 1.0f;
	public float timeToComplete = 120;
	public float splashDuration = 3f;

	private float timeLeftToGenerateScrapMetal;
	private float timePast;
    //private float timeLeftForSplash;


    void CreateUnit()
    {
        var unit =Instantiate(UnitPrefab, Origin.transform.position, Origin.transform.rotation, transform);
        var controller = unit.GetComponent<UnitController>();
        controller.Level = this;
		//var smoothFollow = Camera.main.GetComponent<SmoothFollow> ();
		//smoothFollow.target = controller.transform;
    }

    public TowerController GetNearestTower(Vector3 position)
	{
		var sDistance = Mathf.Infinity;
		TowerController selected = null;
		foreach (var t in Towers)
		{
			var tDistance = (t.Position - position).sqrMagnitude;
			if (tDistance < sDistance)
			{
				selected = t;
				sDistance = tDistance;
			}
		}
		return selected;
	}

	public void PlaceBuilding(Transform building, Vector3 position) {
		var buildingInstance = Instantiate(building, position, Origin.transform.rotation, transform);
		var controller = buildingInstance.GetComponent<ObjectBaseController> ();
		controller.initialize (this);
        SoundController.Current.PlaySound(SoundController.Deploy, 10);
	}


	// Use this for initialization
	void Start () {
		var originTower = Origin.GetComponentInChildren<TowerController>();
		originTower.SetStrobeColor(TowerController.OriginColor);

		var targetTower = Target.GetComponentInChildren<TowerController>();
		targetTower.SetStrobeColor(TowerController.TargetColor);

		CreateUnit(); 

		timeLeftToGenerateScrapMetal = timeToGenerateScrapMetal;
		//timeLeftForSplash = splashDuration;
		timePast = 0;
		ScrapMetalValue.text = scrapMetal.ToString();
	}

    // Update is called once per frame
    void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            if (buildObject != null)
            {
                Vector3 point;

                if (validBuildingPlacement(Input.mousePosition, out point))
                {
                    // Create a particle if hit
                    PlaceBuilding(buildObject, point);
                    buildObject = null;
                }
                else
                {
                    SoundController.Current.PlaySound(SoundController.IllegalBuild);
                }
            }
        }

        timeLeftToGenerateScrapMetal = timeLeftToGenerateScrapMetal - Time.deltaTime;
        if (timeLeftToGenerateScrapMetal <= 0f)
        {
            scrapMetal = scrapMetal + 1;
            timeLeftToGenerateScrapMetal = timeToGenerateScrapMetal;
            ScrapMetalValue.text = scrapMetal.ToString();
        }
        updateTimer();
    }

	private void updateTimer() {
		timePast = timePast + Time.deltaTime;

		var timeLeft = timeToComplete - timePast;
		var minutes = Mathf.Floor (timeLeft / 60f);
		var seconds = Mathf.Floor (timeLeft - (minutes * 60f));
		string secondsStr = seconds.ToString ();
		if (seconds < 10f) {
			secondsStr = string.Concat ("0", secondsStr);
		}

		TimeValue.text = string.Concat(minutes.ToString(), ":", secondsStr);

		if (timePast >= timeToComplete) {
			GameController.Current.SetView (GameController.Views.Lose);
		}
	}

	//Given a mouse position, will calculate where on the ground the mouse clicks in terms of world position and determine if the point conflicts with other objects and the fog of war
	private bool validBuildingPlacement(Vector3 mousePosition, out Vector3 point) {
		// Construct a ray from the current mouse coordinates
		Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
		RaycastHit hit;
		bool validPlacement = true;
		point = new Vector3 (0f, 0f, 0f);

		//Check if coordinate hits the fog of war
		int layerMask = 1 << 8; //Should target only fog of war
		/* Couldn't get this to show NOT black.
		//Texture2D tex = null;
		//Color fowColor;
		if (Physics.Raycast(ray, out hit, 100f, layerMask)) {
			Renderer rend = hit.transform.GetComponent<MeshRenderer>();
			if (rend != null)
				tex = (Texture2D)rend.material.mainTexture;
			fowColor = rend.material.color * ((tex == null) ? Color.white : tex.GetPixel((int)hit.textureCoord.x, (int)hit.textureCoord.y));
			Debug.Log (fowColor);
		}
		*/

		//Get coordinate where click hits the ground
		if (Physics.Raycast (ray, out hit, 100f, ~layerMask)) {
			//Check if coordinate hits the fog of war
			validPlacement = validPointVsFogOfWar(hit.point);
			//Check if new building will hit anything else
			if (validPlacement) {
				validPlacement = validPointVsOtherObjects (hit.point);
			}
			if (validPlacement) {
				point = hit.point;
				return true;
			}
		}

		return false;
	}

	//Check if point hits the fog of war
	private bool validPointVsFogOfWar(Vector3 point) {

		float radius;
		foreach(TowerController t in Towers)
		{
			radius = (float)t.ViewRadius;
			var tDistance = (t.Position - point).sqrMagnitude;
			if (tDistance < Mathf.Pow(radius, 2)) {
				return true;
			}
		}

		return false;
	}

	//Check if point hits any other buildings or obstacles
	private bool validPointVsOtherObjects (Vector3 point) {
		//Test against other objects
		foreach(ObjectBaseController o in Objects)
		{
			var tDistance = (o.Position - point).sqrMagnitude;
			if (tDistance < o.RadiusSqr) {
				return false;
			}
		}

		//TODO test vs. target

		return true;
	}

}
