using System;
using System.Collections;
using UnityEngine;
namespace Mirror.Authenticators
{
    [AddComponentMenu("Network/Authenticators/BasicAuthenticator")]
    public class BasicAuthenticator : NetworkAuthenticator
    {
        [Header("Custom Properties")]
        // set these in the inspector
        public string username;
        public string password;
        #region Messages
        public struct AuthRequestMessage : NetworkMessage
        {
            // use whatever credentials make sense for your game
            // for example, you might want to pass the accessToken if using oauth
            public string authUsername;
            public string authPassword;
        }
        public struct AuthResponseMessage : NetworkMessage
        {
            public byte code;
            public string message;
        }
        #endregion
        #region Server
        /// 
        /// Called on server from StartServer to initialize the Authenticator
        /// Server message handlers should be registered in this method.
        /// 
        public override void OnStartServer()
        {
            // register a handler for the authentication request we expect from client
            NetworkServer.RegisterHandler(OnAuthRequestMessage, false);
        }
        /// 
        /// Called on server from StopServer to reset the Authenticator
        /// Server message handlers should be registered in this method.
        /// 
        public override void OnStopServer()
        {
            // unregister the handler for the authentication request
            NetworkServer.UnregisterHandler();
        }
        /// 
        /// Called on server from OnServerAuthenticateInternal when a client needs to authenticate
        /// 
        /// Connection to client.
        public override void OnServerAuthenticate(NetworkConnection conn)
        {
            // do nothing...wait for AuthRequestMessage from client
        }
        /// 
        /// Called on server when the client's AuthRequestMessage arrives
        /// 
        /// Connection to client.
        /// The message payload
        public void OnAuthRequestMessage(NetworkConnection conn, AuthRequestMessage msg)
        {
            // Debug.LogFormat(LogType.Log, "Authentication Request: {0} {1}", msg.authUsername, msg.authPassword);
            // check the credentials by calling your web server, database table, playfab api, or any method appropriate.
            if (msg.authUsername == username && msg.authPassword == password)
            {
                // create and send msg to client so it knows to proceed
                AuthResponseMessage authResponseMessage = new AuthResponseMessage
                {
                    code = 100,
                    message = "Success"
                };
                conn.Send(authResponseMessage);
                // Accept the successful authentication
                ServerAccept(conn);
            }
            else
            {
                // create and send msg to client so it knows to disconnect
                AuthResponseMessage authResponseMessage = new AuthResponseMessage
                {
                    code = 200,
                    message = "Invalid Credentials"
                };
                conn.Send(authResponseMessage);
                // must set NetworkConnection isAuthenticated = false
                conn.isAuthenticated = false;
                // disconnect the client after 1 second so that response message gets delivered
                StartCoroutine(DelayedDisconnect(conn, 1));
            }
        }
        IEnumerator DelayedDisconnect(NetworkConnection conn, float waitTime)
        {
            yield return new WaitForSeconds(waitTime);
            // Reject the unsuccessful authentication
            ServerReject(conn);
        }
        #endregion
        #region Client
        /// 
        /// Called on client from StartClient to initialize the Authenticator
        /// Client message handlers should be registered in this method.
        /// 
        public override void OnStartClient()
        {
            // register a handler for the authentication response we expect from server
            NetworkClient.RegisterHandler((Action)OnAuthResponseMessage, false);
        }
        /// 
        /// Called on client from StopClient to reset the Authenticator
        /// Client message handlers should be unregistered in this method.
        /// 
        public override void OnStopClient()
        {
            // unregister the handler for the authentication response
            NetworkClient.UnregisterHandler();
        }
        /// 
        /// Called on client from OnClientAuthenticateInternal when a client needs to authenticate
        /// 
        public override void OnClientAuthenticate()
        {
            AuthRequestMessage authRequestMessage = new AuthRequestMessage
            {
                authUsername = username,
                authPassword = password
            };
            NetworkClient.connection.Send(authRequestMessage);
        }
        /// 
        /// Called on client when the server's AuthResponseMessage arrives
        /// 
        /// The message payload
        public void OnAuthResponseMessage(AuthResponseMessage msg)
        {
            if (msg.code == 100)
            {
                // Debug.LogFormat(LogType.Log, "Authentication Response: {0}", msg.message);
                // Authentication has been accepted
                ClientAccept();
            }
            else
            {
                Debug.LogError($"Authentication Response: {msg.message}");
                // Authentication has been rejected
                ClientReject();
            }
        }
        #endregion
    }
}