package cn.reghao.tnb.message.app.rabbit.c;

import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author reghao
 * @date 2021-08-24 17:53:29
 */
public class RpcListenerCallback implements DeliverCallback  {
    private final Channel channel;
    private final Object monitor;

    public RpcListenerCallback(Channel channel, Object monitor) {
        this.channel = channel;
        this.monitor = monitor;
    }

    @Override
    public void handle(String consumerTag, Delivery delivery) throws IOException {
        Result rpcResult = null;
        try {
            String msg = new String(delivery.getBody(), StandardCharsets.UTF_8);
        } catch (RuntimeException e) {
            System.out.println(e.getMessage());
            rpcResult = Result.error("rpc 调用失败: " + e.getMessage());
        } finally {
            if (rpcResult == null) {
                rpcResult = Result.error("rpc 调用失败");
            }
            rpcReply(delivery, rpcResult);

            synchronized (monitor) {
                // 通知 server 线程 consumer 线程执行完成
                monitor.notify();
            }
        }
    }

    /**
     * RPC 调用响应
     *
     * @param
     * @return
     * @date 2021-08-28 下午8:45
     */
    private void rpcReply(Delivery delivery, Result result) throws IOException {
        String correlationId = delivery.getProperties().getCorrelationId();
        String replyTo = delivery.getProperties().getReplyTo();
        AMQP.BasicProperties replyProps = new AMQP.BasicProperties
                .Builder()
                .correlationId(correlationId)
                .build();
        byte[] bytes = JsonConverter.objectToJson(result).getBytes(StandardCharsets.UTF_8);
        channel.basicPublish("", replyTo, true, replyProps, bytes);
        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
}
