using System;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;

//客户端断线重连
public class ClientReconnectingState : ClientConnectingState
{
    Coroutine m_ReconnectCoroutine;

    int curAttempts;

    //断线重连间隔
    const float TimeBetweenAttempts = 5;

    public override void Enter()
    {
        curAttempts = 0;
        m_ReconnectCoroutine = m_ConnectionManager.NetworkManager.StartCoroutine(ReconnectCoroutine());
        //通知UI，转Loading
        MessageCenter.SendMessage(EventDefine.ConnectStatusEvent, ConnectStatus.Reconnecting);
        //MessageCenter.SendMessage(EventDefine.ClientReConnectionEvent, new ReconnectMessage(curAttempts, m_ConnectionManager.ReconnectAttempts));
    }

    public override void Exit()
    {
        if(m_ReconnectCoroutine != null)
        {
            m_ConnectionManager.NetworkManager.StopCoroutine(m_ReconnectCoroutine);
            m_ReconnectCoroutine = null;
        }

        //触发消息
        //MessageCenter.SendMessage(EventDefine.ClientReConnectionEvent, new ReconnectMessage(curAttempts, m_ConnectionManager.ReconnectAttempts));
    }

    //连接成功，跳转到ClientConnectedState
    public override void OnClientConnected(ulong clientId)
    {
        MessageCenter.SendMessage(EventDefine.ConnectStatusEvent, ConnectStatus.Success);

        m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnected);
    }

    //服务端被动断开连接
    public override void OnClientDisconnect(ulong _)
    {
        if(curAttempts < m_ConnectionManager.ReconnectAttempts)
        {
            //次数没到。继续重连
            m_ReconnectCoroutine = m_ConnectionManager.NetworkManager.StartCoroutine(ReconnectCoroutine());
        }
        else
        {
            //次数到了，还是连不上，跳转到OfflineState
            MessageCenter.SendMessage(EventDefine.ConnectStatusEvent, ConnectStatus.GenericDisconnect);

            m_ConnectionManager.ChangeState(m_ConnectionManager.m_Offline);
        }
    }

    //服务端主动断开连接。切换到DisconnectingWithReasonState。异常处理
    public override void OnDisconnectReasonReceived(ConnectStatus disconnectReason)
    {
        MessageCenter.SendMessage(EventDefine.ConnectStatusEvent, disconnectReason);
        //MessageCenter.SendMessage(EventDefine.ClientDisConnectionEvent, disconnectReason);

        switch(disconnectReason)
        {
            case ConnectStatus.UserRequestedDisconnect:
            case ConnectStatus.HostEndedSession:
            case ConnectStatus.ServerFull:
                m_ConnectionManager.ChangeState(m_ConnectionManager.m_DisconnectingWithReason);
                break;
        }
    }

    //开启断线重连
    IEnumerator ReconnectCoroutine()
    {
        //如果不是第一次重连，则等待一段时间（当问题是临时的，可以预留一些时间让其自修复）。也可以用Exponential Backoff方式来处理
        if(curAttempts > 0)
        {
            yield return new WaitForSeconds(TimeBetweenAttempts);
        }

        Debug.Log("Lost connection to host, trying to reconnect...");

        //先关闭
        m_ConnectionManager.NetworkManager.Shutdown();

        //等待直到NetworkManager完全关闭
        yield return new WaitWhile(() => m_ConnectionManager.NetworkManager.ShutdownInProgress);

        //重连次数++
        curAttempts++;

        Debug.Log($"Reconnecting attempt {curAttempts}/{m_ConnectionManager.ReconnectAttempts}...");

        //触发消息
        //MessageCenter.SendMessage(EventDefine.ConnectStatusEvent, ConnectStatus.Reconnecting);
        //MessageCenter.SendMessage(EventDefine.ClientReConnectionEvent, new ReconnectMessage(curAttempts, m_ConnectionManager.ReconnectAttempts));

        //开始连接
        Task connectingClient = ConnectClientAsync();

        yield return new WaitUntil(() => connectingClient.IsCompleted);
    }
}
