package com.muyu.kafka;

import com.alibaba.fastjson.JSON;
import com.muyu.iotDB.service.IotDbServer;
import com.muyu.mqtt.dao.MessageData;
import lombok.extern.log4j.Log4j2;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.admin.CreatePartitionsResult;
import org.apache.kafka.clients.admin.NewPartitions;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.Node;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.header.internals.RecordHeader;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.rmi.ServerException;
import java.util.*;

@Log4j2
@Service
public class KafkaPCUtils {
    @Resource
    private IotDbServer iotDbServer;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    public void sendCallbackOneMessage(String topic, MessageData vehicle) {
        String vin = vehicle.getVin();
        String vehicleString = JSON.toJSONString(vehicle);
        log.info("向主题：[{}]，发送消息：{}", topic, vehicle);
        String bootstrapServers = "127.0.0.1:9092";

        // 设置生产者属性
        Properties properties = new Properties();
        properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        // 创建生产者
        KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
        // 创建分区
        AdminClient adminClient = AdminClient.create(properties);
        CreatePartitionsResult partitions = adminClient.createPartitions(new HashMap() {{
            put(topic, NewPartitions.increaseTo(8, null));
        }});
        // 节点集合
        List<Node> list = new ArrayList<>();
        list.add(new Node(0, "127.0.0.1", 9092));
        // 节点分区列表
        List<PartitionInfo> partitionInfos = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            partitionInfos.add(new PartitionInfo(topic,i,null,null,null));
        }

        int partition = new CustomPartitioner().partition(
                topic,
                vin,
                vin.getBytes(),
                vehicleString,
                vehicleString.getBytes(),
                new Cluster(
                        "uqU0Vo8_TiaV2Xp0kzczaA",
                        list,
                        partitionInfos,
                        new HashSet<String>() {},
                        new HashSet<>())
        );
        log.info("当前获取分区：[{}]",partition);
        // 创建消息  主题  key  分区  值
        ProducerRecord<String, String> record = new ProducerRecord<>(topic,partition, vin, vehicleString);
        record.headers().add(new RecordHeader("type", "String".getBytes(StandardCharsets.UTF_8)));

        // 发送消息 有回执
        producer.send(record, (matadata, exception) -> {
            if (exception == null) {
//                int partition = matadata.partition();
                log.info("消息发送成功,topic:[{}],分区为:[{}]", topic, partition);

            } else {
                log.info("消息发送失败,topic:[{}],异常信息：[{}]", topic, exception.getMessage());
            }
        });
        // 关闭生产者
        producer.close();
    }


    @KafkaListener(topics = {"test1"},groupId = "Topics")
    public void onNormalMessage1(ConsumerRecord<String, Object> record) throws ServerException, IoTDBConnectionException, StatementExecutionException {
        String value = (String) record.value();
        MessageData messageData = JSON.parseObject(value, MessageData.class);
        System.out.println("简单消费：" + record.topic() + "-" + record.partition() + "=" +
                record.value());
        iotDbServer.add(messageData);
    }

}
