using NaughtyAttributes;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

//Could be a singleton
public class GameFlowManager : MonoBehaviour {
	[SerializeField] [Required]
	GameTimer gameTimer = null!;
	/// <summary>
	/// True if time is frozen (Start, Pause Menu, Dead)
	/// </summary>
	/// <remarks>Could be renamed appropriately</remarks>
	[field: SerializeField]
	public bool Paused { get; private set; } = true;
	public BaseState CurrentState { get; private set; } = null!;
	bool lastStartButton;
	bool lastAcceptButton;

	#region  Unity Messages
	void Awake() => CurrentState = new StartFlowState(this);

	void Start() => CurrentState.EnterState();
	#endregion

	void SetPause(bool value) {
		Debug.Log($"Setting pause to {value}");
		Paused = value;
		Time.timeScale = value ? 0f : 1f;
	}

	public void GameOver() => SwitchState(new DeadFlowState(this));

	#region Inputs
	public void OnStart(InputAction.CallbackContext ctx) {
		if (!ctx.WasPressedThisFrame(ref lastStartButton))
			return;

		if (CurrentState is StartFlowState)
			SwitchState(new GameplayFlowState(this));
	}
	
	public void OnAccept(InputAction.CallbackContext ctx) {
		if (!ctx.WasPressedThisFrame(ref lastAcceptButton))
			return;

		if (CurrentState is DeadFlowState deadState)
			deadState.ReloadGame();
	}
	#endregion

	#region States
	void SwitchState(BaseState newState) {
		CurrentState.LeaveState();
		CurrentState = newState;
		newState.EnterState();
	}
	
	abstract class GameFlowState : BaseState {
		readonly protected GameFlowManager gameFlowManager; 
		
		protected GameFlowState(GameFlowManager gameFlowManager) {
			this.gameFlowManager = gameFlowManager;
		}
	}

	class StartFlowState : GameFlowState {
		public StartFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {}
		
		public override void EnterState() {
			base.EnterState();
			
			Debug.Log("Press Start to start...!");
			gameFlowManager.SetPause(true);
		}

		public override void LeaveState() {
			Debug.Log("Let the games begin!!");
		}
	}
	class GameplayFlowState : GameFlowState {
		public GameplayFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {}
		
		public override void EnterState() {
			base.EnterState();
			
			gameFlowManager.gameTimer.StartTimer();
			gameFlowManager.SetPause(false);
		}

		public override void LeaveState() {
			base.LeaveState();
			
			gameFlowManager.gameTimer.PauseTimer();
		}
	}
	class PauseMenuFlowState : GameFlowState {
		public PauseMenuFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {}
		
		public override void EnterState() {
			base.EnterState();
			gameFlowManager.SetPause(true);
		}
	}
	class DeadFlowState : GameFlowState {
		public DeadFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {}
		
		public override void EnterState() {
			base.EnterState();
			
			Debug.Log("You died!\nPress Accept to restart!");
			gameFlowManager.SetPause(true);
		}

		public void ReloadGame() {
			Debug.Log("Reloading scene...");
			SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
		}
	}
	#endregion
}