using UnityEngine;
using Gamelogic.Grids;
using System.Linq;

namespace Gamelogic.Grids.Examples
{
	public class SuperMaze : GLMonoBehaviour, IResetable
	{
		private readonly RectPoint PlayerSpawnPoint = new RectPoint(1, 1);
		private readonly RectPoint GoalPoint = new RectPoint(13, 13);

		public GameObject gridRoot;
		public WallCell wallCellPrefab;
		public GameObject playerPrefab;
		public GameObject goalPrefab;
		public Texture2D noiseImage;

		//public GameObject endMessage;

		public static bool gameOver;

		public InspectableVectorPoint bigSize;
		public InspectableVectorPoint smallSize;
		public Vector2 cellDimensions;

		private IMap3D<RectPoint> map;
		private RectGrid<WallCell> grid;



		private GameObject player;
		private GameObject goal;


		private IMap<RectPoint> noiseMap;


		public void Start()
		{
			Screen.lockCursor = true;

			Reset();
		}

		public void Update()
		{
			if (Input.GetKeyDown(KeyCode.R))
			{
				Reset();
			}
			CheckGameOver();
		}

		public void Reset()
		{
			Debug.Log("Reset()");
			gridRoot.transform.DestroyChildren();
			//endMessage.SetActive(false);

			BuildGrid();
			InitGame();
		}

		private void BuildGrid()
		{
			Debug.Log("BuildGrid()");
			grid = RectGrid<WallCell>.Rectangle(25, 25);

			Debug.Log("BigMap");
			map = new RectMap(cellDimensions*1f)
				.WithWindow(ExampleUtils.ScreenRect)
				.AlignMiddleCenter(grid)
				.To3DXZ();

			Debug.Log("CreateCells");
			foreach (var point in grid)
			{
				WallCell wallCell = Instantiate(wallCellPrefab);
				wallCell.transform.parent = gridRoot.transform;
				wallCell.transform.localScale = Vector3.one;
				wallCell.transform.localPosition = map[point];

				wallCell.Traversable = (point.GetColor3() != 0);
				grid[point] = wallCell;
			}

			Debug.Log("BuildingMaze");
			var walls = MazeAlgorithms.GenerateMazeWalls(grid).ToList();
			foreach (var wall in walls)
			{
				grid[wall].Traversable = false;
			}

			Debug.Log("Setup Lights");
			noiseMap = new RectMap(Vector2.one)
				.WithWindow(ExampleUtils.ScreenRect)
				.AlignMiddle(grid)
				.Scale(15f);

			foreach (var point in grid)
			{

				if (point.GetColor4() != 0)
				{
					grid[point].DisableLight();
					//continue;
				}

				var t = noiseImage.GetPixel((int) noiseMap[point].x,
					(int) noiseMap[point].y).r*2 - .5f;

				Color newColor =
					Color.Lerp
						(
							ExampleUtils.Colors[6],
							ExampleUtils.Colors[7], t

						);

				grid[point].LightColor = newColor;
			}

			Debug.Log("DONE");
		}

		private void InitGame()
		{
			gameOver = false;
			SpawnPlayerAt(PlayerSpawnPoint);
			CreateGoalAt(GoalPoint);
		}

		private void SpawnPlayerAt(RectPoint point)
		{
			player = Instantiate(playerPrefab);

			player.transform.parent = gridRoot.transform;
			player.transform.localScale = Vector3.one;
			player.transform.localPosition = map[point] + Vector3.up*1.5f;
		}

		private void CreateGoalAt(RectPoint point)
		{
			goal = Instantiate(goalPrefab);

			goal.transform.parent = gridRoot.transform;
			goal.transform.localScale = Vector3.one;
			goal.transform.localPosition = map[point] + Vector3.up*1.5f;
		}

		private void CheckGameOver()
		{
			//Debug.Log(Vector3.Distance(goal.transform.localPosition, player.transform.localPosition).ToString());
			if (Vector3.Distance(goal.transform.localPosition, player.transform.localPosition) < 1.2f)
			{
				GameOver();
			}
		}

		private void GameOver()
		{
			Debug.Log("Game Over");
			gameOver = true;
			//endMessage.SetActive(true);

			//player.GetComponent<CharacterMotor>().canControl = false;
		}
	}
}