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

namespace Gamelogic.Grids.Examples
{
	public class SPOD : GLMonoBehaviour
	{
		private const float NewCoinCooldown = 15f;

		public GameObject gridRoot;
		public PlatformCell cellPrefab;
		public GameObject playerPrefab;
		public GameObject coinPrefab;
		public GUIText coinNumberLable;
		public float deathHeight;

		public Vector3 coinSize;

		public int gridSize = 5;
		private static FlatHexGrid<PlatformCell> grid;

		public Vector2 cellDimensions;
		public float cellPadding = 0;
		private IMap3D<FlatHexPoint> map;

		private GameObject player;
		private static int coinsCollected;

		public void Start()
		{
			Reset();
		}

		public void Update()
		{
			coinNumberLable.text = coinsCollected.ToString();

			if (Input.GetKeyDown(KeyCode.R))
			{
				Reset();
			}
			if (player.transform.localPosition.y < deathHeight)
			{
				GameOver();
			}
		}

		public void Reset()
		{
			gridRoot.transform.DestroyChildren();

			BuildGrid();
			BuildMap();
			CreateCells();
			InitGame();
		}

		private void BuildGrid()
		{
			grid = FlatHexGrid<PlatformCell>.Diamond(gridSize);
		}

		private void BuildMap()
		{
			var paddedDimensions = new Vector2(cellDimensions.x + cellPadding, cellDimensions.y + cellPadding);

			map = new FlatHexMap(paddedDimensions)
				.AnchorCellMiddleCenter()
				.WithWindow(ExampleUtils.ScreenRect)
				.AlignMiddleCenter(grid)
				.To3DXZ();
		}

		private void CreateCells()
		{
			const float cellThickness = 0.25f;

			foreach (var gridPoint in grid)
			{
				PlatformCell p = Instantiate(cellPrefab);
				p.transform.parent = gridRoot.transform;
				p.transform.localScale = new Vector3(cellDimensions.x, cellThickness, cellDimensions.y);
				p.transform.localPosition = map[gridPoint];

				grid[gridPoint] = p;
			}
		}

		private void InitGame()
		{
			coinsCollected = 0;

			SpawnPlayer();

			const int AmountOfCoinsToCreate = 40;

			for (int i = 0; i < AmountOfCoinsToCreate; i++)
			{
				CreateCoinAt(grid.Where(p => grid[p].ContainsCoin == false).RandomItem());
			}

			StartCoroutine(NewCoin());
		}

		private void SpawnPlayer()
		{
			FlatHexPoint spawnPoint = grid.Where(p => grid[p].Traversable == true).RandomItem();

			player = Instantiate(playerPrefab);
			player.transform.parent = gridRoot.transform;

			player.transform.localPosition = map[spawnPoint] + Vector3.up*1.5f;
			grid[spawnPoint].RemoveBehaviours();
		}

		private void CreateCoinAt(FlatHexPoint spawnPoint)
		{
			GameObject c = Instantiate(coinPrefab);
			c.transform.parent = gridRoot.transform;
			c.transform.localScale = coinSize;
			c.transform.localPosition = map[spawnPoint] + Vector3.up*1f;
			grid[spawnPoint].ContainsCoin = true;
		}

		public static void CoinCollectedAt(FlatHexPoint coinPosition)
		{
			grid[coinPosition].ContainsCoin = false;
			coinsCollected++;
		}

		private IEnumerator NewCoin()
		{
			while (true)
			{
				yield return new WaitForSeconds(NewCoinCooldown);

				var newPoint = grid.Where(p => grid[p].ContainsCoin == false).RandomItem();
				CreateCoinAt(newPoint);
			}
		}

		private void GameOver()
		{
			Reset();
		}
	}
}