using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Networking.Server;

public abstract class GameMode : ScriptableObject
{

    [SerializeField]
    [Tooltip("Scene to load which contains Gamemode UI")]
    private string GameModeScene;

    [SerializeField]
    [Tooltip("Round Times are acessed from the top down")]
    private List<float> RoundTimes;

    public Action GameStartEvent;
    public Action RoundStartEvent;
    public Action AllPlayersMovedEvent;
    public Action RoundEndEvent;
    public Action OnGameOverEvent;

    private List<float> gameTimes;

    
    protected abstract void OnGameStart(PlayerData[] allPlayers);

    /// <summary>
    /// Called at the beginning of a new Round
    /// </summary>
    protected abstract void OnRoundStart(PlayerData[] allPlayers);

    /// <summary>
    /// Called for each player after they finished one move. Even if they didn't move!
    /// </summary>
    /// <param name="character">Character which moved</param>
    /// <param name="client">Client which controls character</param>
    /// <param name="currentBlock">Block which the character finished on</param>
    protected abstract void OnPlayerFinishedMove(Character character, ClientData client, Block currentBlock);

    /// <summary>
    /// Called once after every player has finished one move
    /// </summary>
    /// <param name="allCharacters">List of all player Info</param>
    protected abstract void OnAllPlayersFinishedMove(PlayerData[] allPlayers);

    public abstract bool isGameOver(PlayerData[] allPlayers);

    protected abstract void OnRoundEnd(PlayerData[] allPlayers);

    protected abstract void OnGameOver(PlayerData[] allPlayers);

    public float GetRoundTime()
    {
        float retVal = gameTimes[0];
        if (gameTimes.Count > 1)
            gameTimes.RemoveAt(0);
        return retVal;
    }

    public void GameStart(PlayerData[] allPlayers)
    {
        gameTimes = new List<float>(RoundTimes);

        if (!String.IsNullOrEmpty(GameModeScene))
            UnityEngine.SceneManagement.SceneManager.LoadScene(GameModeScene,UnityEngine.SceneManagement.LoadSceneMode.Additive);

        for(int i = 0; i < allPlayers.Length; i++)
        {
            allPlayers[i].client.SceneScore = 0;
        }
        OnGameStart(allPlayers);
    }

    public void RoundStart(PlayerData[] allPlayers)
    {
        OnRoundStart(allPlayers);
        RoundStartEvent?.Invoke();
    }

    public void FinishedMove(PlayerData[] allPlayers)
    {
        OnAllPlayersFinishedMove(allPlayers);
        AllPlayersMovedEvent?.Invoke();
    }

    public void OnePlayerMoved(PlayerData player)
    {
        OnPlayerFinishedMove(player.character, player.client, player.character.CurrentBlock);
    }

    public void RoundEnd(PlayerData[] allPlayers)
    {
        OnRoundEnd(allPlayers);
        RoundEndEvent?.Invoke();
    }

    public void GameOver(PlayerData[] allPlayers)
    {
        OnGameOver(allPlayers);
        OnGameOverEvent?.Invoke();
    }
}
