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


public class GameController : MonoBehaviour {
	public Crew SelectedCrew;

	private Dictionary<GameObject, RoomJobPair> roomNodes;

	void Awake()
	{
		// Add all the possible nodes which we can visit.
		roomNodes = new Dictionary<GameObject, RoomJobPair>();

		// Find the rooms which are tagged as 'Room', seemple.
		var rooms = GameObject.FindGameObjectsWithTag ("Room");

		foreach (var room in rooms) {
			// So now you can add as many rooms as you like and you can then navigate to any of them!
			roomNodes.Add (room, new RoomJobPair(room.GetComponent<BaseRoom>(), room.GetComponent<Job>()));
		}
	}

    public BaseRoom GetRoomByName(string roomName)
    {
        return roomNodes.FirstOrDefault(x => x.Key.name.Equals(roomName)).Value.Room;
    }

	public BaseRoom GetRoomByJob(Job job)
	{
		return roomNodes.FirstOrDefault(x => x.Value.Job != null && x.Value.Job.Equals(job)).Value.Room;
	}

    public Job GetJobByRoomName(string roomName)
    {
        return roomNodes.FirstOrDefault(x => x.Key.name.Equals(roomName)).Value.Job;
    }

    public RoomJobPair GetRoomAndJobByRoomName(string roomName)
    {
        return roomNodes.FirstOrDefault(x => x.Key.name.Equals(roomName)).Value;
    }

    public Transform GetRoomTransformByRoomName(string roomName)
    {
        return roomNodes.FirstOrDefault(x => x.Key.name.Equals(roomName)).Key.transform;
    }

    public BaseRoom DetectRoom(Vector3 position)
    {
		return roomNodes.FirstOrDefault(x => x.Key.GetComponent<Collider2D>().bounds.Contains(position)).Value.Room;
    }

	public IEnumerator<BaseRoom> GetRooms()
	{
		foreach (var room in roomNodes) {
			yield return room.Value.Room;
		}
	}

	public List<BaseRoom> GetDamagedRooms()
	{
		List<BaseRoom> returnValues = new List<BaseRoom>();

		foreach (var item in roomNodes)
		{
			if (item.Value.Room.IsRoomDamaged ())
				returnValues.Add (item.Value.Room);
		}
		return returnValues.OrderBy (x => x.RoomHealth ()).ToList ();
	}

	public List<Transform> GetPath(BaseRoom a, BaseRoom b)
	{
		// Get us a nice list to store our points in. Mmmmmm, tasty.
		List<Transform> returnPath = new List<Transform> ();

		// Right, are we trying to access a room on the same level?
		if (a.deckLevel == b.deckLevel) {
			// Add that bad boy to the list.
			returnPath.Add (b.gameObject.transform);
		} 
		// Too bad. Okay, are we currently on a stair...able room?
		else if (a.deckLevel != b.deckLevel && a.ContainsStairs) {
			// Huzzah! Now determine whether we are going up or down, then add it to the list again.
			if (b.deckLevel - a.deckLevel > 0) {
				returnPath.Add (roomNodes.FirstOrDefault (x => x.Value.Room.deckLevel == a.deckLevel + 1 && x.Value.Room.ContainsStairs).Key.transform);
			} else {
				returnPath.Add (roomNodes.FirstOrDefault (x => x.Value.Room.deckLevel == a.deckLevel - 1 && x.Value.Room.ContainsStairs).Key.transform);
			}
		}
		// No luck again? Alright, just find the sodding stairs on the level.
		else {
			returnPath.Add(roomNodes.FirstOrDefault (x => x.Value.Room.deckLevel == a.deckLevel && x.Value.Room.ContainsStairs) .Key.transform);
		}

		// Okay, okay...okay. Does the destination position match our last items position?
		if (b.transform.position != returnPath.LastOrDefault().transform.position) {
			// What a skally wag! Time to recursive this shizzle up the code-nizzle until we find our destination :D
			returnPath.AddRange (GetPath(roomNodes.FirstOrDefault (x => x.Key.transform ==  returnPath.LastOrDefault().transform).Value.Room, b));
		}
		// Return that completed, red delicious, babe zizzling, bacon loving list of paths the crew member needs to take.
		return returnPath;
	}
}
