using ExitGames.Client.Photon;
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class NetworkManager : MonoBehaviourPunCallbacks, IOnEventCallback
{
    [SerializeField] private GameEvent_RiftSettings onSpawnRiftRequest;

    [SerializeField] private StringSharedField charSelected;

    [SerializeField] private GameEvent_Player onPlayerJoinedParty;
    [SerializeField] private GameEvent_Player onPlayerLeftParty;
    [SerializeField] private GameEvent_Player onPlayerVoted;
    [SerializeField] private GameEvent_Player onPlayerVoteCanceled;
    [SerializeField] private GameEvent onLoadLevelStarting;
    [SerializeField] private GameEvent onJoinedRoom;

    [SerializeField] private GameEventListener_ZoneData onGameSceneLoaded;
    [SerializeField] private GameEventListener_PhotonView onPlayerSpawned;
    [SerializeField] private TMP_Text changeLevelVoteText;



    private int count = 0;
    private bool changeLevelVoted = false;
    private Button voteButton;
    //private object inProgress = false;

    private Dictionary<Player, bool> playerVoted = new Dictionary<Player, bool>();

    public List<Player> party = new List<Player>();


    readonly string huntersInn = "4-RiftHuntersInn";
    readonly string skellyard = "4-Skellyard";



    private void Awake()
    {
        DontDestroyOnLoad(this);

        onGameSceneLoaded.Response.AddListener(OnGameSceneLoaded);
        onPlayerSpawned.Response.AddListener(OnPlayerSpawned);
    }

    // Start is called before the first frame update
    void Start()
    {
        PhotonNetwork.AutomaticallySyncScene = true;
        PhotonNetwork.ConnectUsingSettings();
        Debug.Log("Connecting..");
    }

    public override void OnConnectedToMaster()
    {
        Debug.Log("Connected.");
        PhotonNetwork.JoinLobby();
        Debug.Log("Joining Lobby..");
    }

    public override void OnJoinedLobby()
    {
        Debug.Log("Lobby joined.");
        //PhotonNetwork.JoinOrCreateRoom("Sprint_01", new RoomOptions { MaxPlayers = 0, EmptyRoomTtl = 0 }, TypedLobby.Default);
        //Debug.Log("Joining Game..");
    }

    public override void OnJoinedRoom()
    {
        Debug.Log("Party \"" + PhotonNetwork.CurrentRoom.Name + "\" joined.");

        ClearVotes();

        if (!SceneManager.GetActiveScene().name.Contains(huntersInn))
        {
            if (PhotonNetwork.IsMasterClient)
            {
                PhotonNetwork.LoadLevel(huntersInn);
            }
        }

        onJoinedRoom.Raise();
    }

    public void OnGameSceneLoaded(ZoneData zoneData)
    {
        ClearVotes();
        StartCoroutine(SpawnCharacterWithDelay());
        if (PhotonNetwork.LocalPlayer.IsMasterClient && zoneData.isHostileZone)
            StartCoroutine(SpawnEnemiesWithDelay(zoneData));
    }

    public IEnumerator SpawnCharacterWithDelay()
    {
        yield return new WaitUntil(() => PhotonNetwork.InRoom);
        PhotonNetwork.Instantiate("PlayableCharacters/" + charSelected.Value, Vector3.zero + new Vector3(3 * PhotonNetwork.LocalPlayer.ActorNumber, 0, 0), Quaternion.identity);
    }

   /* private void Update()
    {
        if (!PhotonNetwork.LocalPlayer.IsMasterClient) return;

        if (Input.GetKeyDown(KeyCode.S))
        {
            onSpawnRiftRequest.Raise(new RiftSettings()
            {
                zoneData = rift,
                riftIndex = Random.Range(0, 5),
                enemyIndexes_Quantity = new Dictionary<int, int>()
                {
                    { 0, Random.Range(2, 6) },
                    { 1, Random.Range(2, 6) }
                }
            });
            //PhotonNetwork.InstantiateRoomObject("AngrySkellyPrefab", new Vector3(-10, 0, 10), Quaternion.identity);
        }

        if (Input.GetKeyDown(KeyCode.F1))
        {
            PhotonNetwork.LoadLevel(huntersInn);
        }

        if (Input.GetKeyDown(KeyCode.F2))
        {
            PhotonNetwork.LoadLevel(skellyard);
        }
    }*/


    public IEnumerator SpawnEnemiesWithDelay(ZoneData zoneData)
    {
        yield return new WaitForSeconds(1f);

        onSpawnRiftRequest.Raise(new RiftSettings()
        {
            zoneData = zoneData,
            numberOfWaves = Random.Range(GameConstants.GameBalancing.MinimumNumberOfWavesPerRift, GameConstants.GameBalancing.MaximumNumberOfWavesPerRift),
            riftIndex = Random.Range(0, 5),
            enemyIndexes_Quantity = new Dictionary<int, int>()
                {
                    { 0, Random.Range(GameConstants.GameBalancing.MinimumQuantityIndex0, GameConstants.GameBalancing.MaximumQuantityIndex0) },
                    { 1, Random.Range(GameConstants.GameBalancing.MinimumQuantityIndex1, GameConstants.GameBalancing.MaximumQuantityIndex1) }
                },
            bossIndex = Random.Range(0, 2)
        }); ;
    }

    public override void OnPlayerEnteredRoom(Player newPlayer)
    {
        Debug.Log("New player joined: " + newPlayer.NickName);

        playerVoted.Add(newPlayer, false);
        changeLevelVoteText.text = $"Votes: {count}/{PhotonNetwork.PlayerList.Length}";
        //party.Add(newPlayer);
        //onPlayerJoinedParty.Raise(newPlayer);
    }
    public override void OnPlayerLeftRoom(Player otherPlayer)
    {
        if (playerVoted.ContainsKey(otherPlayer))
        {
            if (playerVoted[otherPlayer])
                count--;
            playerVoted.Remove(otherPlayer);
        }
        if (party.Contains(otherPlayer))
        {
            party.Remove(otherPlayer);
            onPlayerLeftParty.Raise(otherPlayer);
        }
        changeLevelVoteText.text = $"Votes: {count}/{PhotonNetwork.PlayerList.Length}";
        Debug.Log("Player left: " + otherPlayer.NickName);
    }
    public void OnPlayerSpawned(PhotonView photonView)
    {
        party.Add(photonView.Owner);
        onPlayerJoinedParty.Raise(photonView.Owner);
    }

    public void ChangeLevelVote(Button button)
    {
        if (!PhotonNetwork.IsConnected) return;
        if (changeLevelVoted) return;

        voteButton = button;
        changeLevelVoted = true;
        voteButton.interactable = false;
        if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
        {
            CountVote(PhotonNetwork.LocalPlayer);
            Send_All_OnLoadLevelStarting();
        }
        else
        {
            CountVote(PhotonNetwork.LocalPlayer);
            RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.Others };
            PhotonNetwork.RaiseEvent(GameConstants.NetworkEventCodes.ChangeLevelVoted, PhotonNetwork.LocalPlayer, raiseEventOptions, SendOptions.SendReliable);
            if (PhotonNetwork.IsMasterClient)
            {
                if (count >= PhotonNetwork.CurrentRoom.PlayerCount)
                {
                    Send_All_OnLoadLevelStarting();
                }
            }
        }

    }
    public void CancelChangeLevelVote()
    {
        if (!PhotonNetwork.IsConnected) return;
        if (!changeLevelVoted) return;

        changeLevelVoted = false;
        if (voteButton != null)
            voteButton.interactable = true;

        RemoveVote(PhotonNetwork.LocalPlayer);

        RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.Others };
        PhotonNetwork.RaiseEvent(GameConstants.NetworkEventCodes.CancelChangeLevelVoted, PhotonNetwork.LocalPlayer, raiseEventOptions, SendOptions.SendReliable);
    }

    private void Send_All_OnLoadLevelStarting()
    {
        RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.All };
        PhotonNetwork.RaiseEvent(GameConstants.NetworkEventCodes.LoadLevelStarting, 0, raiseEventOptions, SendOptions.SendReliable);
    }

    public void OnEvent(EventData photonEvent)
    {
        if (photonEvent.Code == GameConstants.NetworkEventCodes.ChangeLevelVoted)
        {
            Player player = (Player)photonEvent.CustomData;
            Debug.Log(player);
            Debug.Log(player.ActorNumber);
            Debug.Log(player.NickName);
            if (PhotonNetwork.IsMasterClient)
            {
                CountVote(player);
                if (count >= PhotonNetwork.CurrentRoom.PlayerCount)
                {
                    Send_All_OnLoadLevelStarting();
                }
            }
            else
            {
                CountVote(player);
            }
        }
        if (photonEvent.Code == GameConstants.NetworkEventCodes.CancelChangeLevelVoted)
        {
            Player player = (Player)photonEvent.CustomData;
            Debug.Log(player);
            Debug.Log(player.ActorNumber);
            Debug.Log(player.NickName);

            RemoveVote(player);
        }
        if (photonEvent.Code == GameConstants.NetworkEventCodes.LoadLevelStarting)
        {
            Debug.Log("loadlevelStarting");
            UpdateGameStateOnLoadLevelStarting();
            if (PhotonNetwork.IsMasterClient)
                NetworkLoadVotedLevel();
        }
    }

    private void CountVote(Player player)
    {
        playerVoted[player] = true;
        count++;
        changeLevelVoteText.text = $"Votes: {count}/{PhotonNetwork.PlayerList.Length}";
        onPlayerVoted.Raise(player);
    }
    private void RemoveVote(Player player)
    {
        playerVoted[player] = false;
        count--;
        if (count < 0) count = 0;
        changeLevelVoteText.text = $"Votes: {count}/{PhotonNetwork.PlayerList.Length}";
        onPlayerVoteCanceled.Raise(player);
    }
    private void ClearVotes()
    {
        List<Player> keys = new List<Player>(playerVoted.Keys);

        for (int i = 0; i < keys.Count; i++)
        {
            playerVoted[keys[i]] = false;
        }
        count = 0;
        if (voteButton != null)
            voteButton.interactable = true;
        changeLevelVoted = false;
        changeLevelVoteText.text = $"Votes: {count}/{PhotonNetwork.PlayerList.Length}";
    }

    private void NetworkLoadVotedLevel()
    {
        UpdateRoomPropertiesInProgress(false);

        StartCoroutine(NetworkLoadRestartWithDelay());
    }
    private IEnumerator NetworkLoadRestartWithDelay()
    {
        yield return new WaitForSeconds(1.5f);

        PhotonNetwork.LoadLevel(SceneManager.GetActiveScene().name == huntersInn ? skellyard : huntersInn);
    }

    private void UpdateGameStateOnLoadLevelStarting()
    {
        onLoadLevelStarting.Raise();
    }

    private void CheckRoomProperties()
    {
        //if (PhotonNetwork.CurrentRoom.CustomProperties.TryGetValue("inProgress", out inProgress))
        //{
        //    Debug.Log("Got inProgress from properties: " + (bool)inProgress + " ");
        //}
        PhotonNetwork.Instantiate(charSelected.Value, Vector3.zero + new Vector3(3 * PhotonNetwork.LocalPlayer.ActorNumber, 0, 0), Quaternion.identity);

    }
    public override void OnRoomPropertiesUpdate(ExitGames.Client.Photon.Hashtable propertiesThatChanged)
    {

    }
    public void UpdateRoomPropertiesInProgress(bool inProgress)
    {
        ExitGames.Client.Photon.Hashtable ht = new ExitGames.Client.Photon.Hashtable { { "inProgress", inProgress } };
        PhotonNetwork.CurrentRoom.SetCustomProperties(ht);
    }
}
