using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using Unity.Services.Authentication;
using Unity.Services.Core;
using Sirenix.OdinInspector;
using System;
using Unity.Netcode;
using Unity.Services.Lobbies.Models;
using UnityEngine.Events;
using TMPro;
using Cysharp.Threading.Tasks;
using System.Threading;
#if UNITY_EDITOR
using ParrelSync;
#endif

public class QuickLobbyServiceModule : MonoBehaviour
{
    public MatchmakingService matchmakingService;

    public TextMeshProUGUI statusText;
    public UnityEvent OnDidJoinMatch;

    Task task;

    private CancellationTokenSource cancelToken;

    public void JoinQuickMatch()
    {
        task = _JoinQuickMatch();
    }

    public void Cancel()
    {
        cancelToken?.Cancel();
        Debug.Log("Cancel Join Quick Match");
        NetworkManager.Singleton.Shutdown();
        if (AuthenticationService.Instance.IsSignedIn) {
            AuthenticationService.Instance.SignOut();
        }
    }

    async Task _JoinQuickMatch()
    {
        cancelToken = new CancellationTokenSource();
        while (!cancelToken.IsCancellationRequested) {
            if (NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer) {
                Debug.Log("Shutting Down Previous Match...");
                NetworkManager.Singleton.Shutdown();
            }

            Debug.Log("Join Quick Match");
            if (Authentication.IsLoggedIn() == false) {
                Debug.Log("Will log in");
                statusText.text = "Loging in to service...";
                await Authentication.Login();
                statusText.text = "Logged into service...";
                Debug.Log("Did log in");
            }
            if (Authentication.IsLoggedIn() == false) {
                statusText.text = "Login attemp failed, trying again...";
                await UniTask.Delay(TimeSpan.FromMilliseconds(2000), ignoreTimeScale: false);
                continue;
            }
            Debug.Log("Will find match");
            statusText.text = "Finding Match...";
            var allLobbies = await matchmakingService.GatherLobbies();
            if (allLobbies.Count == 0) {
                Debug.Log("Could not find Match");
                statusText.text = "Waiting for more matches...";
                await UniTask.Delay(TimeSpan.FromMilliseconds(2000), ignoreTimeScale: false);
                continue;
            }
            statusText.text = "Found Match";
            Debug.Log("Did find match");

            for (int i = 0; i < allLobbies.Count; i++) {
                try {
                    statusText.text = "Joining Match...";
                    Debug.Log("Will join match");
                    await matchmakingService.JoinLobbyWithAllocation(allLobbies[i].Id);

                    if (NetworkManager.Singleton.StartClient() == false) {
                        statusText.text = "Could not join match, trying again...";
                        await UniTask.Delay(TimeSpan.FromMilliseconds(2000), ignoreTimeScale: false);
                        continue;
                    }
                    NetworkSceneDirector.instance.OnClientStarted(true);
                    Debug.Log("Did join match");
                    statusText.text = "Did join Match...";
                    OnDidJoinMatch?.Invoke();
                    return;
                }
                catch (Exception e) {
                    Debug.LogError(e);
                }
            }

            Debug.Log("Could not find match");
            statusText.text = "Could not find a Match, trying again...";
            await UniTask.Delay(TimeSpan.FromMilliseconds(2000), ignoreTimeScale: false);
        }
    }
}
