using System.Collections.Generic;
using UnityEngine;

public class SimonGameManager : MonoBehaviour
{
	// ********************************************************************************
	// Constants
	enum SimonGameState
	{
		Ready,
		Say,
		Listen,
		Over
	}

	// ********************************************************************************
	// Members
	List<int> _sequence = new();
	SimonGameState _state;
	float _stateTime;
	int _sayLength;
	int _sayStep;
	int _listenStep;

	// ********************************************************************************
	// Properties
	public GameObject[] SayObject;

	// ********************************************************************************
	// Unity messages
	void Start()
	{
		for (int i = 0; i < 5; i++)
			_sequence.Add(Random.Range(0, 4));

		_state = SimonGameState.Ready;
		_stateTime = 0.0f;
		_sayLength = 1;
	}

	void Update()
	{
		switch (_state)
		{
			case SimonGameState.Ready:
				Update_Ready();
				break;
			case SimonGameState.Say:
				Update_Say();
				break;
			case SimonGameState.Listen:
				Update_Listen();
				break;
		}
	}

	// ********************************************************************************
	// State handlers
	void Update_Ready()
	{
		if (_stateTime > 2.0f)
		{
			Debug.Log("seq: ");
			for (int i = 0; i < _sequence.Count; i++)
				Debug.Log(_sequence[i]);
			Debug.Log("saying " + _sayLength);

			_stateTime = 0.0f;
			_state = SimonGameState.Say;
			_sayStep = 0;
			return;
		}

		_stateTime += Time.deltaTime;
	}

	void Update_Say()
	{
		if (_stateTime < 1.0f)
		{
			for (int i = 0; i < 4; i++)
			{
				SayObject[i].transform.localScale = Vector3.one * ((i == _sequence[_sayStep]) ? 2.0f : 1.0f);
			}
		}
		else if (_stateTime < 1.5f)
		{
			for (int i = 0; i < 4; i++)
			{
				SayObject[i].transform.localScale = Vector3.one;
			}
		}
		else
		{
			_sayStep++;
			_stateTime = 0.0f;

			if (_sayStep == _sayLength)
			{
				_state = SimonGameState.Listen;
				_stateTime = 0.9f;
				_listenStep = 0;
				Debug.Log("listening");
				return;
			}
		}

		_stateTime += Time.deltaTime;
	}

	void Update_Listen()
	{
		if (_stateTime >= 1.0f)
		{
			for (int i = 0; i < 4; i++)
			{
				SayObject[i].transform.localScale = Vector3.one;
			}
		}
		
		if ((_stateTime > 2.5f) && (_listenStep == _sayLength))
		{
			_sayLength++;
			if (_sayLength > _sequence.Count)
			{
				Debug.Log("simon game win");
				_state = SimonGameState.Over;
				return;
			}

			Debug.Log("saying " + _sayLength);
			_stateTime = 0.0f;
			_sayStep = 0;
			_state = SimonGameState.Say;
			return;
		}

		_stateTime += Time.deltaTime;
	}

	// ********************************************************************************
	// Input events
	void OnUp()
	{
		Hear(0);
	}

	void OnDown()
	{
		Hear(1);
	}

	void OnLeft()
	{
		Hear(2);
	}

	void OnRight()
	{
		Hear(3);
	}

	// ********************************************************************************
	// Utilities
	void Hear(int i)
	{
		if (_state != SimonGameState.Listen)
			return;

		if (_stateTime < 1.0f)
			return;

		if (_listenStep == _sayLength)
			return;

		SayObject[i].transform.localScale = Vector3.one * 2.0f;

		if (i == _sequence[_listenStep])
		{
			_stateTime = 0.0f;
			
			_listenStep++;
		}
		else
		{
			_state = SimonGameState.Over;
			Debug.Log("simon game over");
		}
	}
}
