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

[CreateAssetMenu(menuName = "Major Project/GameModes/Color Collide", order = 201)]
public class ColorGameMode : GameMode
{

    public int MaxRound = 5;
    public string nextScene = "ServerTestScene";
    List<ClientData> ConnectedClients;
    public Material OverlayMaterial;


    public int RoundCount { get; private set; }
    private Dictionary<ClientData, List<Block>> BlocksOwned;

    /// <summary>
    /// Called once all players have finished their moves but before the Objective is checked
    /// </summary>
    protected override void OnRoundEnd(PlayerData[] allPlayers)
    {
        RoundCount++;
    }


    /// <summary>
    /// Checks if the Game is finished
    /// </summary>
    /// <returns>returns if game is finished</returns>
    public override bool isGameOver(PlayerData[] allPlayers)
    {
        return (RoundCount >= MaxRound -1);
    }


    /// <summary>
    /// Called once per player after they have moved onto a block
    /// </summary>
    /// <param name="character">Character which moved</param>
    /// <param name="client">Client of the character</param>
    /// <param name="currentBlock">Block moved onto</param>
    protected override void OnPlayerFinishedMove(Character character, ClientData client, Block currentBlock)
    {
        ClientData OwnedClient;
        Material overlay = null;
        if (isOwned(currentBlock, out OwnedClient))
        {
            if (OwnedClient == client)
                return;

            BlocksOwned[OwnedClient].Remove(currentBlock);

            foreach (Material mat in currentBlock.GetComponent<Renderer>().materials)
            {
                if (mat.name == OverlayMaterial.name + " (Instance)")
                    overlay = mat;
            }
        }

        if (overlay == null)
        {
            overlay = new Material(OverlayMaterial);
            List<Material> mats = new List<Material>(currentBlock.GetComponent<Renderer>().materials);
            mats.Add(overlay);
            currentBlock.GetComponent<Renderer>().materials = mats.ToArray();
        }

        overlay.SetColor("_NewColor", client.Color);

        if (!BlocksOwned.ContainsKey(client))
            BlocksOwned.Add(client, new List<Block>());

        BlocksOwned[client].Add(currentBlock);
         
        if (overlay != null)
            currentBlock.StartCoroutine(AnimateBlock(overlay, 0.25f));
    }

    protected override void OnRoundStart(PlayerData[] allPlayers)
    {
        
    }

    protected override void OnAllPlayersFinishedMove(PlayerData[] allPlayers)
    {
        foreach (PlayerData player in allPlayers)
        {
            if (BlocksOwned.ContainsKey(player.client))
                player.client.SceneScore = BlocksOwned[player.client].Count;
            else
                player.client.SceneScore = 0;
        }
    }

    protected override void OnGameOver(PlayerData[] allPlayers)
    {
        throw new System.NotImplementedException();
    }

    private bool isOwned(Block block, out ClientData client)
    {
        client = null;

        foreach (KeyValuePair<ClientData, List<Block>> ownedList in BlocksOwned)
        {
            if (ownedList.Value.Contains(block))
            {
                client = ownedList.Key;
                return true;
            }
        }

        return false;
    }

    private IEnumerator AnimateBlock(Material mat, float time)
    {

        float timeElasped = 0;

        while (timeElasped < time)
        {
            mat.SetFloat("_Multiplier", (timeElasped / time));
            yield return new WaitForEndOfFrame();

            timeElasped += Time.deltaTime;
        }

        mat.SetFloat("_Multiplier", 1);
    }

    protected override void OnGameStart(PlayerData[] allPlayers)
    {
        BlocksOwned = new Dictionary<ClientData, List<Block>>();
        RoundCount = 0;
        for(int i = 0; i < allPlayers.Length; i++)
        {
            OnPlayerFinishedMove(allPlayers[i].character, allPlayers[i].client, allPlayers[i].character.CurrentBlock);
        }
    }
}
