using System.Collections;
using Google.Protobuf;
using NativeWebSocket;
using UnityEngine;
using UnityEngine.Networking;

[System.Serializable]
public class LoginResponse
{
    public int code;
    public string msg;
    public Data data;
}

[System.Serializable]
public class Data
{
    public long usn;
    public string name;
    public string accessToken;
    public string refreshToken;
}

public class SocketManager : MonoBehaviour
{
    private WebSocket _ws;

    public static SocketManager Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
    }

    public async void Connect()
    {
        var token = await GetTokenAsync();

        // _ws = new WebSocket($"wss://www.hlsq.asia/ws/?token={Random.Range(1, 1000)}");
        _ws = new WebSocket($"ws://127.0.0.1:8501/?token={token}");

        _ws.OnOpen += () => { Debug.Log("Connection open!"); };

        _ws.OnError += (e) => { Debug.Log("Error! " + e); };

        _ws.OnClose += (e) => { Debug.Log("Connection closed!"); };

        _ws.OnMessage += (bytes) =>
        {
            var message = Message.Parser.ParseFrom(bytes);
            Debug.Log("OnMessage: " + message.ID);
            SocketMessageManager.Instance.TriggerEvent(message.ID, message.Payload);
        };

        await _ws.Connect();
    }

    private async System.Threading.Tasks.Task<string> GetTokenAsync()
    {
        string token = "";
        var tcs = new System.Threading.Tasks.TaskCompletionSource<string>();

        StartCoroutine(HttpPost("http://127.0.0.1:8503/gw/login", "{\"phone\": \"1234\", \"code\": \"1234\"}", (resp) =>
        {
            try
            {
                var r = JsonUtility.FromJson<LoginResponse>(resp);
                token = r.data.accessToken;
                tcs.SetResult(token);
            }
            catch (System.Exception e)
            {
                tcs.SetException(e);
            }
        }));

        return await tcs.Task;
    }

    public void SendMessage(MessageID id, IMessage msg)
    {
        var m = new Message
        {
            ID = id,
            Payload = ByteString.CopyFrom(msg.ToByteArray())
        };
        _ws.Send(m.ToByteArray());
    }

    public IEnumerator HttpPost(string url, string jsonData, System.Action<string> callback)
    {
        var request = new UnityWebRequest(url, "POST");
        var bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        yield return request.SendWebRequest();

        if (request.result == UnityWebRequest.Result.Success)
        {
            callback?.Invoke(request.downloadHandler.text);
        }
        else
        {
            Debug.LogError("HTTP POST Error: " + request.error);
        }

        request.Dispose();
    }

    private void Update()
    {
#if !UNITY_WEBGL || UNITY_EDITOR
        _ws?.DispatchMessageQueue();
#endif
    }

    private async void OnApplicationQuit()
    {
        await _ws.Close();
    }
}