package com.mortals.xhx.queue.kafka;

import com.mortals.xhx.queue.TbQueueCallback;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.header.Header;
import org.apache.kafka.common.header.internals.RecordHeader;

import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * kafka 生产者模板
 *
 * @author: zxfei
 * @date: 2021/11/22 11:23
 */
@Data
@Slf4j
public class TbKafkaProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> {

    /**
     * 生产者
     */
    private KafkaProducer<String, byte[]> producer;
    /**
     * kafka 配置信息
     */
    private TbKafkaSettings settings;

    private String defaultTopic;
    /**
     * topic组
     */
    private Set<TopicPartitionInfo> topics;

    @Builder
    private TbKafkaProducerTemplate(TbKafkaSettings settings,String defaultTopic) {
        this.settings = settings;
        //初始化生产者参数
        this.producer = new KafkaProducer<>(settings.toProducerProps());
        this.defaultTopic = defaultTopic;
        topics = ConcurrentHashMap.newKeySet();
    }

    @Override
    public void init() {
    }

    @Override
    public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) {
        String key = msg.getKey().toString();
        byte[] data = msg.getData();
        ProducerRecord<String, byte[]> record;
        if (tpi.getTopic() == null) {
            tpi.setTopic(this.defaultTopic);
        }
        Iterable<Header> headers = msg.getHeaders().getData().entrySet().stream().map(e -> new RecordHeader(e.getKey(), e.getValue())).collect(Collectors.toList());
        record = new ProducerRecord<>(tpi.getTopic(), null, key, data, headers);
        producer.send(record, (metadata, exception) -> {
            if (exception == null) {
                if (callback != null) {
                    callback.onSuccess(new KafkaTbQueueMsgMetadata(metadata));
                }
            } else {
                if (callback != null) {
                    callback.onFailure(exception);
                } else {
                    log.warn("Producer template failure: {}", exception.getMessage(), exception);
                }
            }
        });

    }


    @Override
    public void stop() {
        if (producer != null) {
            producer.close();
        }
    }


}
