﻿using Gamelogic.AbstractStrategy.Grids;
using Gamelogic.Diagnostics;
using UnityEngine;
using UnityEngine.UI;
using Gamelogic.Grids;

namespace Gamelogic.AbstractStrategy.Examples
{
	public class BasicDraughts : MonoBehaviour
	{
		public Text messageText;

		private GridGameManager manager;
		private IPieceProperties selectedPiece;
		private Player<RectPoint, GridGamePieceSettings> redPlayer, bluePlayer;
		
		public void Start()
		{
			messageText.gameObject.SetActive(false);

			InitializeGameManager();
			InitializePlayers();

			manager.StartGame();
			manager.OnGameOver += () => ShowMessage("Game Over! Press Space to restart");
		}

		private void ShowMessage(string message)
		{
			messageText.gameObject.SetActive(true);
			messageText.text = message;
		}
		
		public void Update()
		{
			if (Input.GetKeyDown(KeyCode.Space))
			{
				messageText.gameObject.SetActive(false);
				manager.StartGame();
				DeselectPiece();
			}
		}

		private void InitializeGameManager()
		{
			manager = GetComponent<GridGameManager>();

			if (manager == null)
			{
				GLDebug.LogError("You must have a GridGameManager attached to the same game object as this component");
			}
		}

		private void InitializePlayers()
		{
			redPlayer = new GridHumanPlayer("red");
			bluePlayer = new GridHumanPlayer("blue");

			manager.RegisterPlayer(redPlayer);
			manager.RegisterPlayer(bluePlayer);
		}

		public void OnClick(RectPoint point)
		{
			var currentPlayer = manager.CurrentPlayer;
			if (currentPlayer is GridHumanPlayer &&
				manager.MoveManager.Done)
			{
				// If a block is occupied, try to select
				var state = manager.State;

				var piece = state.TestPosition(point);
				if (piece != null)
				{
					if (piece.playerID == currentPlayer.PlayerID)
					{
						SelectPiece(piece);
					}
				}
				else if (selectedPiece != null)
				{
					// Try to commit move
					var selectedPos = state.FindPiece(selectedPiece);
					var move = state.CreateMovePieceMove(selectedPiece, selectedPos, point);
					if (manager.CommitMove(move))
					{
						DeselectPiece();
					}
					else
					{
						// If we're trying to move to any tile 4 manhattan distance away, try and capture a piece in the middle
						var moveDist = selectedPos.DistanceFrom(point);
						if (moveDist == 4)
						{
							var centerPos = (point + selectedPos) / 2;
							var capturePiece = state.TestPosition(centerPos);
							if (capturePiece != null)
							{
								move = state.CreateCapturePieceMove(selectedPiece, capturePiece, selectedPos, point, centerPos);
								if (manager.CommitMove(move))
								{
									DeselectPiece();
								}
							}
						}
					}
				}
			}
		}


		private void DeselectPiece()
		{
			if (selectedPiece != null)
			{
				UpdateVisualSelectionState(false);
			}

			selectedPiece = null;
		}


		private void SelectPiece(IPieceProperties piece)
		{
			if (selectedPiece != null)
			{
				DeselectPiece();
			}

			selectedPiece = piece;

			UpdateVisualSelectionState(true);
		}

		private void UpdateVisualSelectionState(bool selectionOn)
		{
			var visualPiece = manager.GetExistingVisualPiece(selectedPiece);
			var sprite = visualPiece.GetComponentInChildren<SpriteRenderer>();

			if (sprite != null)
			{
				var colour = sprite.color;
				colour.a = selectionOn ? 0.8f : 1.0f;
				sprite.color = colour;
			}
		}

	}
}