﻿using AsmodeeDigital.Common.Plugin.UI;
using AsmodeeDigital.PlayReal.Plugin.Manager;
using AsmodeeDigital.PlayReal.Samples.Views;
using com.daysofwonder;
using com.daysofwonder.async;
using System;
using System.Collections.Generic;
using UnityEngine.UI;

namespace AsmodeeDigital.PlayReal.Samples.UI.LobbyGame
{
    public class PopupWaitingGame : Popup
    {
        /// <summary>
        /// UI references of PopupWaitingGame
        /// </summary>
        [Serializable]
        public class UIPopupWaitingGame
        {
            public List<LobbyPlayerSlot> LobbyPlayerSlots;

            public Button AcceptButton;
            public Button DeclineButton;
            public Button LeaveButton;
        }

        public UIPopupWaitingGame uiPopupWaitingGame;

        public void Show(string message, List<Player> playersInvited)
        {
            if (LobbyGameView.IsDestroyed)
                return;

            ui.Message.text = message;

            Show(playersInvited.Count, playersInvited);

            ui.Message.gameObject.SetActive(true);
            uiPopupWaitingGame.AcceptButton.gameObject.SetActive(true);
            uiPopupWaitingGame.DeclineButton.gameObject.SetActive(true);
            uiPopupWaitingGame.LeaveButton.gameObject.SetActive(false);
        }

        public void Show(int countPlayers, List<Player> playersInvited = null)
        {
            if (LobbyGameView.IsDestroyed)
                return;

            base.Show();

            if (playersInvited == null)
                playersInvited = new List<Player>();

            if (!playersInvited.Exists(p => p.w_w_w_id == PlayRealManager.Instance.Persistence.ConnectedPlayer.w_w_w_id))
                playersInvited.Add(PlayRealManager.Instance.Persistence.ConnectedPlayer);

            uiPopupWaitingGame.LobbyPlayerSlots.ForEach(lps => lps.HideSlot());

            ui.Message.gameObject.SetActive(false);
            ui.CloseButton.gameObject.SetActive(false);
            uiPopupWaitingGame.AcceptButton.gameObject.SetActive(false);
            uiPopupWaitingGame.DeclineButton.gameObject.SetActive(false);
            uiPopupWaitingGame.LeaveButton.gameObject.SetActive(true);

            if (countPlayers < playersInvited.Count)
                countPlayers = playersInvited.Count;

            for (int i = 0; i < countPlayers; i++)
            {
                if (i < playersInvited.Count)
                {
                    AddPlayer(playersInvited[i]);
                }
                else
                {
                    uiPopupWaitingGame.LobbyPlayerSlots[i].SetEmptySlot();
                }
            }
        }

        private void AddPlayer(Player player)
        {
            LobbyPlayerSlot lobbyPlayerSlot = uiPopupWaitingGame.LobbyPlayerSlots.Find(lps => lps.State == LobbyPlayerSlotState.Empty);

            if (lobbyPlayerSlot == null)
                lobbyPlayerSlot = uiPopupWaitingGame.LobbyPlayerSlots.Find(lps => lps.State == LobbyPlayerSlotState.Hidden);

            if (lobbyPlayerSlot != null)
            {
                bool isCurrentPlayer = player.w_w_w_id == PlayRealManager.Instance.Persistence.ConnectedPlayer.w_w_w_id;

                if (isCurrentPlayer)
                    lobbyPlayerSlot.SetCurrentPlayerInSlot();
                else
                    lobbyPlayerSlot.SetPlayer(player);

                lobbyPlayerSlot.ui.AcceptIcon.gameObject.SetActive(false);
                lobbyPlayerSlot.ui.DeclineIcon.gameObject.SetActive(false);

                if (PlayRealManager.Instance.Persistence.InvitationAcceptedByPlayers != null &&
                    PlayRealManager.Instance.Persistence.InvitationAcceptedByPlayers.Contains(player.w_w_w_id))
                {
                    lobbyPlayerSlot.ui.AcceptIcon.gameObject.SetActive(true);
                }
            }
        }

        public void RemovePlayer(Player player)
        {
            LobbyPlayerSlot lobbyPlayerSlot = GetLobbyPlayerSlot(player);

            if (lobbyPlayerSlot != null)
            {
                lobbyPlayerSlot.SetEmptySlot();
            }
        }

        public void ShowDenied(LobbyJoinDeniedRequest.JoinError cause)
        {
            uiPopupWaitingGame.LobbyPlayerSlots.ForEach(lps => lps.HideSlot());

            ui.Message.gameObject.SetActive(true);
            ui.Message.text = String.Format("You can't join the game : {0}", cause.ToString());

            ui.CloseButton.gameObject.SetActive(true);
            uiPopupWaitingGame.AcceptButton.gameObject.SetActive(false);
            uiPopupWaitingGame.DeclineButton.gameObject.SetActive(false);
            uiPopupWaitingGame.LeaveButton.gameObject.SetActive(false);
        }

        public void PlayerAcceptInvitation(Player player)
        {
            LobbyPlayerSlot lobbyPlayerSlot = GetLobbyPlayerSlot(player);

            if (lobbyPlayerSlot != null)
                lobbyPlayerSlot.ui.AcceptIcon.gameObject.SetActive(true);
        }

        public void PlayerRejectInvitation(Player player)
        {
            LobbyPlayerSlot lobbyPlayerSlot = GetLobbyPlayerSlot(player);

            if (lobbyPlayerSlot != null)
                lobbyPlayerSlot.ui.DeclineIcon.gameObject.SetActive(true);

            ui.Message.gameObject.SetActive(true);
            ui.Message.text = String.Format("{0} rejected the invitation.\r\nThe game is cancelled", player.name);

            ui.CloseButton.gameObject.SetActive(true);
            uiPopupWaitingGame.AcceptButton.gameObject.SetActive(false);
            uiPopupWaitingGame.DeclineButton.gameObject.SetActive(false);
            uiPopupWaitingGame.LeaveButton.gameObject.SetActive(false);
        }

        private LobbyPlayerSlot GetLobbyPlayerSlot(Player player)
        {
            LobbyPlayerSlot lobbyPlayerSlot = uiPopupWaitingGame.LobbyPlayerSlots.Find(lps => lps.OnlinePlayer != null && lps.OnlinePlayer.w_w_w_id == player.w_w_w_id);

            return lobbyPlayerSlot;
        }
    }
}
