package com.tsi.comm.server.kafka;

import com.tsi.comm.server.config.TsiKafkaProducerConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.common.TopicPartition;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
import org.springframework.kafka.listener.ConsumerAwareRebalanceListener;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collection;

@Slf4j
@Service
public class KafkaConsumerService {

    private final TsiKafkaProducerConfig config;

    //private KafkaConsumer<String, byte[]> consumer;
    private ConcurrentMessageListenerContainer<String, Long> kafkaListenerContainer;

    public KafkaConsumerService(TsiKafkaProducerConfig config) {
        this.config = config;
    }

    @PostConstruct
    void init() {
        log.info("[{}] ------------------", this.getClass().getSimpleName());
        start();
    }

    public void start() {

        if (this.kafkaListenerContainer != null) {
            if (!this.kafkaListenerContainer.isRunning()) {
                log.warn("kafkaListenerContainer restart");
                this.kafkaListenerContainer.start();
            }
            return;
        }

        ContainerProperties containerProperties = new ContainerProperties(TsiKafkaProducerConfig.CVIM_PING);
        containerProperties.setGroupId(this.config.getGroupId());
        containerProperties.setPollTimeout(5000);
        //containerProperties.setAckMode(ContainerProperties.AckMode.MANUAL);
        containerProperties.setMessageListener(new TsiKafkaConsumerWorker());
        containerProperties.setConsumerRebalanceListener(new ConsumerAwareRebalanceListener() {
            @Override
            public void onPartitionsRevokedBeforeCommit(Consumer<?, ?> consumer, Collection<TopicPartition> partitions) {
            }
            @Override
            public void onPartitionsRevokedAfterCommit(Consumer<?, ?> consumer, Collection<TopicPartition> partitions) {
            }
            @Override
            public void onPartitionsAssigned(Consumer<?, ?> consumer, Collection<TopicPartition> partitions) {
                consumer.seekToEnd(partitions);
            }
        });

        ConsumerFactory<String, Long> consumerFactory = new DefaultKafkaConsumerFactory<>(this.config.getConsumerPropertiesMap());
        this.kafkaListenerContainer = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
        this.kafkaListenerContainer.setBeanName("consumer");
        this.kafkaListenerContainer.setConcurrency(1);
        this.kafkaListenerContainer.setErrorHandler((thrownException, data) -> {
            log.error("kafkaListenerContainer error: {}", thrownException.getMessage());
            this.kafkaListenerContainer.stop();
        });

        this.kafkaListenerContainer.start();
    }

    public void shutdown() {
        try {
            //if (this.consumer != null) {
            //    this.consumer.close();;
            //}
            if (this.kafkaListenerContainer != null) {
                this.kafkaListenerContainer.stop();
            }
        }
        catch(Exception ignored) {
        }
    }
}
