using UnityEngine;
using System.Collections;
using Gamelogic.Grids2;

public class SpawnActor : MonoBehaviour 
{
    public int FirstLevel = 0;
    public int LastLevel = 9999;

    public int MinX = -1, MinY = -1, MaxX = -1, MaxY = -1;  // Set in Editor.  -1 for no constraint
    private int xmin, xmax, ymin, ymax;                     // Usable values after constraint and map bounds checking

    public Transform ActorPrefab;

	void Start () 
    {
        int d = GameController.CurrentDepth;
        if (d < FirstLevel || d > LastLevel)
            return;

        ComputeSpawnBounds();
        Spawn();
	}

    private void ComputeSpawnBounds()
    {
        GridPoint2 mapmax = GameMap.instance.Grid.Bounds.Size;

        xmin = (MinX == -1) ? 1 : MinX;
        ymin = (MinY == -1) ? 1 : MinY;

        xmax = (MaxX == -1) ? mapmax.X-2 : Mathf.Min(mapmax.X, MaxX);
        ymax = (MaxY == -1) ? mapmax.Y-2 : Mathf.Min(mapmax.Y, MaxY);
    }
	
    private void Spawn()
    {
        SpawnPrefabAt(ActorPrefab, GetLocation());
    }

    public static Transform SpawnPrefabAt(Transform prefab, GridPoint2 pos)
    {
        if (!GameMap.Contains(pos))
        {
            Debug.LogError("ERROR: SpawnPrefabAt cannot spawn " + prefab.name + " at non-existant location " + pos);
            return null;
        }
        
        Transform t = GameObject.Instantiate(prefab);
        t.position = GameMap.Cell[pos].transform.position;

        Actor actor = t.GetComponent<Actor>();
        if (actor == null)
        {
            //Debug.Log("SpawnActor spawning non-actor " + t);
            t.SendMessage("RegisterAsContents", pos, SendMessageOptions.DontRequireReceiver);
            return t;
        }

        if (GameMap.Cell[pos].HasActor())
        {
            Debug.LogError("ERROR: SpawnPrefabAt cannot place " + actor.name + " at unavailable location " + actor.Location);
        } 

        actor.Location = pos;

        GameMap.Cell[actor.Location].SetActor(actor);
        return t;
    }

    private GridPoint2 GetLocation()
    {
        // TODO guess-and-test w/ max tries is not a perfect approach, consider replacing with building a list of valids, drawing from that at random, throw if impossible

        int tries = 0;
        GridPoint2 candidate;
        do
        {           
            candidate = new GridPoint2(Random.Range(xmin, xmax+1), Random.Range(ymin, ymax+1));
            tries++;
        } while (!GameMap.Available(candidate) && tries < 100);

        if (tries >= 100)
            throw new System.Exception("Failed to Spawn " + ActorPrefab + " after 100 tries in area [" + xmin + "-" + xmax + ", " + ymin + "-" + ymax + "]");

        return candidate;
    }

}
