using MessagePack;
using NetMQ;
using NetMQ.Sockets;

namespace Hawkeye.VisionBuilder.Workflow.DataTransfer;
[MessagePackObject]
public class MethodCall
{
    [Key(0)]
    public string Name { get; set; }
    [Key(1)]
    public List<object> Parameters { get; set; }

    public MethodCall()
    {
    }

    public MethodCall(string name, params object[] parameters)
    {
        Name=name;
        Parameters=new List<object>(parameters);
    }
}
[MessagePackObject]
public class TransferData
{
    [Key(0)]
    public ETransferType DataType { get; set; }
    [Key(1)]
    public int Int { get; set; }
    [Key(2)]
    public string String { get; set; }
    [Key(3)]
    public byte[] Bytes { get; set; }
    [Key(4)]
    public float[] Floats { get; set; }

    public static implicit operator TransferData(int value)
    {
        return new TransferData()
        {
            DataType = ETransferType.Int,
            Int = value
        };
    }

    public static implicit operator TransferData(string value)
    {
        return new TransferData()
        {
            DataType = ETransferType.String,
            String = value
        };
    }

    public static implicit operator TransferData(byte[] value)
    {
        return new TransferData()
        {
            DataType = ETransferType.Bytes,
            Bytes = value
        };
    }
    public static implicit operator TransferData(float[] value)
    {
        return new TransferData()
        {
            DataType = ETransferType.Floats,
            Floats = value
        };
    }
}

public enum ETransferType
{
    Void=0,
    Int=1,
    String=2,
    Bytes=3,
    Floats=4
}
public class CSharpDataTransferMQRPC
{
    private object _syncObject = new object();
    private readonly ResponseSocket _server;

    public CSharpDataTransferMQRPC()
    {
        this._server = new ResponseSocket();
        _server.Bind("tcp://*:5555");
        

    }
    
    public T TransferData<T>(MethodCall call)
    {
        lock (_syncObject)
        {
            return TransferDataInternal<T>(call);
        }

    }

    private T TransferDataInternal<T>(MethodCall call)
    {
        Console.WriteLine("Waiting for request");
        _server.ReceiveFrameBytes();

        
        Console.WriteLine("Sending response");

        var serialized = MessagePack.MessagePackSerializer.Serialize(call);

        _server.SendFrame(serialized);
        


        Console.WriteLine("Waiting for request");
        var result = _server.ReceiveFrameBytes();
        
        var decoded=MessagePackSerializer.Deserialize<object>(result);

        
        
        _server.SendFrame("OK");

      
        return (T)Convert.ChangeType(decoded, typeof(T));
    }
}