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

using CloudPointRpc;
using System.Runtime.CompilerServices;

public class RpcTest : MonoBehaviour
{
    private static Queue<Task> _callbackTasks = new Queue<Task>();
    private static BlendShaderController controller;
    private static CancellationTokenSource cts;

    [AOT.MonoPInvokeCallback(typeof(CrpcTestApi.RpcStringCallback))]
    public static IntPtr RpcStringCallback(IntPtr rpcString)
    {
        var rpc = new RpcString(rpcString);
        var message = rpc.Data;
        rpc.Dispose();
        var tcs = new TaskCompletionSource<bool>();

        var task = new Task(async () => {
            Debug.Log($"[RpcTest] Callback received: {message}");
            controller.SaveTextureAsync(tcs);
            Debug.Log("After Saving inside task");
                }, cts.Token);

        lock (_callbackTasks)
        {
            _callbackTasks.Enqueue(task);
        }

        try
        {
            task.Wait(cts.Token);
            tcs.Task.Wait(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Debug.Log("Waiting was canceled");
        }
        var responce = new RpcString("1");
        Debug.Log("Finished");
        return responce.Handle;
    }

    void Start()
    {
        controller = FindFirstObjectByType<BlendShaderController>();
        cts = new CancellationTokenSource();

        CrpcTestApi.crpc_test_init();
        CrpcTestExtensions.CrpcTestAddMethod(RpcStringCallback, "test_method");
        Debug.Log("[RpcTest] Initialized and method added");
    }

    private void Update()
    {
        lock (_callbackTasks)
        {
            while (_callbackTasks.Count > 0)
            {
                var task = _callbackTasks.Dequeue();
                task.RunSynchronously();
                Debug.Log("Update");
            }
        }
    }

    private void OnDestroy()
    {
        Debug.Log("Call deinit1");
        lock (_callbackTasks)
        {
            Debug.Log("Call deinit2");
            _callbackTasks.Clear();
        }

        Debug.Log("Call deinit finnaly");
        cts.Cancel();

        //Task.Run(() => CrpcTestApi.crpc_test_deinit());
        CrpcTestApi.crpc_test_deinit();
    }
}