#if UNITY_WEBGL
using Microsoft.VisualStudio.Threading;
using Nerdbank.Streams;
using StreamJsonRpc;
using StreamJsonRpc.Protocol;
using StreamJsonRpc.Reflection;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityWebSocket.WebGL;

public class WebGLMessageHandler : MessageHandlerBase
{
    private static AsyncQueue<byte[]> receiveQueue = new();
    public override bool CanWrite => true;
    public override bool CanRead => true;
    public WebSocket WebSocket { get { return webSocket; } }
    private WebSocket webSocket;

    internal event WebSocketJsonRpcMessageHandlerSendEventHandler OnSend;

    private static readonly ConcurrentDictionary<WebSocket, WebGLMessageHandler> instanceMap = new();

    private void PushReceivedMessage(WebSocket context, byte[] message)
    {
        try
        {
            ThreadPool.QueueUserWorkItem((o) => receiveQueue.Enqueue(message));
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.Message);
        }
    }

    public WebGLMessageHandler(WebSocket context, IJsonRpcMessageFormatter formatter) : base(formatter)
    {
        receiveQueue = new AsyncQueue<byte[]>();
        webSocket = context;
        webSocket.OnMessage += WebSocket_OnMessage;
        instanceMap[context] = this;
    }
    private void WebSocket_OnMessage(object sender, UnityWebSocket.MessageEventArgs e)
    {
        PushReceivedMessage(WebSocket, e.RawData);
    }
    public WebGLMessageHandler(IJsonRpcMessageFormatter formatter) : base(formatter)
    {
    }

    protected override ValueTask FlushAsync(CancellationToken cancellationToken)
    {
        return default;
    }

    protected async override ValueTask<JsonRpcMessage> ReadCoreAsync(CancellationToken cancellationToken)
    {

        byte[] data = await receiveQueue.DequeueAsync(cancellationToken).ConfigureAwait(false);
       // Debug.LogError("ȡݣ" + data.Length);

        cancellationToken.ThrowIfCancellationRequested();
        JsonRpcMessage jsonRpcMessage = Formatter.Deserialize(new ReadOnlySequence<byte>(data));
        return jsonRpcMessage;
    }

    protected async override ValueTask WriteCoreAsync(JsonRpcMessage content, CancellationToken cancellationToken)
    {
        try
        {
            byte[] data;
            using (var contentSequenceBuilder = new Sequence<byte>())
            {
                Formatter.Serialize(contentSequenceBuilder, content);
                data = contentSequenceBuilder.AsReadOnlySequence.ToArray();
                if (this.Formatter is IJsonRpcFormatterTracingCallbacks tracer)
                {
                    tracer.OnSerializationComplete(content, contentSequenceBuilder);
                }
                //Debug.LogError("ݣ" + data.Length);

                WebSocketJsonRpcMessageHandlerSendEventArgs e = new(webSocket, data);
                OnSend?.Invoke(this, e);
                cancellationToken.ThrowIfCancellationRequested();

                if (e.SendTask != null)
                {
                    await e.SendTask.WithCancellation(cancellationToken).ConfigureAwait(false);
                }
            }


        }
        catch (Exception ex)
        {

            Debug.LogError(ex.Message);
        }

    }
    protected override void Dispose(bool disposing)
    {
        //if (disposing)
        //{
        //    instanceMap.TryRemove(WebSocket, out _);
        //    receiveQueue.Complete();
        //    while (!receiveQueue.IsEmpty)
        //    {
        //        receiveQueue.TryDequeue(out _);
        //    }
        //}
        base.Dispose(disposing);
    }
}
public delegate void WebSocketJsonRpcMessageHandlerSendEventHandler(object sender, WebSocketJsonRpcMessageHandlerSendEventArgs e);

public class WebSocketJsonRpcMessageHandlerSendEventArgs : EventArgs
{
    public Task SendTask { get; internal set; }
    public WebSocket Context { get; }
    public byte[] Message { get; }
    public WebSocketJsonRpcMessageHandlerSendEventArgs(WebSocket context, byte[] message) : base()
    {
        Context = context;
        Message = message;
        SendTask = context.SendAsync(Message);
    }
}
#endif