package com.mortals.xhx.queue.kafka;

import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.Builder;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;

import java.io.IOException;
import java.time.Duration;
import java.util.*;

/**
 * kafka consumer 消费者模板
 *
 * @author: zxfei
 * @date: 2021/11/22 11:21
 */
@Slf4j
public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<ConsumerRecord<String, byte[]>, T> {
    private final KafkaConsumer<String, byte[]> consumer;

    private final String groupId;

    private final TbKafkaDecoder<T> decoder;

    @Builder
    private TbKafkaConsumerTemplate(TbKafkaSettings settings, String clientId, TbKafkaDecoder<T> decoder, String groupId, String topic) {
        //默认topic
        super(topic);
        Properties props = settings.toConsumerProps();
        //多个输入源的时候 需要配置
        //props.put(ConsumerConfig.CLIENT_ID_CONFIG, clientId);
        if (groupId != null) {
            props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
        }

        this.groupId = groupId;
        this.consumer = new KafkaConsumer<>(props);
        this.decoder = decoder;
    }

    @Override
    protected void doSubscribe(List<String> topicNames) {
        if (!topicNames.isEmpty()) {
            //  topicNames.forEach(admin::createTopicIfNotExists);
            log.info("subscribe topics {}", topicNames);
            consumer.subscribe(topicNames);
        } else {
            log.info("unsubscribe due to empty topic list");
            consumer.unsubscribe();
        }
    }

    @Override
    protected List<ConsumerRecord<String, byte[]>> doPoll(long durationInMillis) {
        ConsumerRecords<String, byte[]> records = consumer.poll(Duration.ofMillis(durationInMillis));

        records.forEach(record -> {
            System.out.printf("topic = %s ,partition = %d,offset = %d, key = %s, value = %s%n", record.topic(), record.partition(),
                    record.offset(), record.key(), record.value());
        });
        if (records.isEmpty()) {
            return Collections.emptyList();
        } else {
            List<ConsumerRecord<String, byte[]>> recordList = new ArrayList<>(256);
            records.forEach(recordList::add);
            return recordList;
        }
    }

    @Override
    public T decode(ConsumerRecord<String, byte[]> record)  {
        return decoder.decode(new KafkaTbQueueMsg(record));
    }

    @Override
    protected void doCommit() {
        //同步提交，线程会阻塞，直到当前批次offset提交成功
        consumer.commitAsync();
    }

    @Override
    protected void doUnsubscribe() {
        log.info("unsubscribe topic and close consumer for topic {}", getTopic());
        if (consumer != null) {
            //consumer.unsubscribe();
            consumer.close();
        }
    }

    public static void main(String[] args) {
        // TbKafkaConsumerTemplate.builder().
    }

    @Override
    public void unsubscribe(Set<TopicPartitionInfo> partitions) {

    }

    @Override
    public String getChannelNumber() {
        return "1231";
    }
}
