package org.ts.ddcs.main;


import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;


import org.springframework.web.bind.annotation.GetMapping;
import org.ts.ddcs.common.constant.KafkaConstants;
import org.ts.ddcs.constant.NetPortStatusConstant;
import org.ts.ddcs.dataStream.DataStreamManageHolder;
import org.ts.ddcs.dataStream.DataStreamManager;
import org.ts.ddcs.datatemplate.DataTemplateManageHolder;
import org.ts.ddcs.datatemplate.DataTemplateManager;
import org.ts.ddcs.net.DataChannel;
import org.ts.ddcs.net.DataChannelHolder;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.*;


/**
 * 数据报文处理主类
 *
 * @author dylan
 */
@Component
@Slf4j
public class MainProcessor {
    private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("public-process-pool-%d").build();
    /**
     * 公共线程池
     **/
    private static ExecutorService publicThreadPool = new ThreadPoolExecutor(2, 16,
            0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy());


    private RocksDB storeCache;

    @Value("${spring.application.name}")
    public String serverName;

    @Value("${tsywxt-config.template.path}")
    public String templatesDirPath;

    @Value("${tsywxt-config.template.templates}")
    public String templates;

    @Value("${tsywxt-config.nio.listener.tcp-port}")
    public String tcpPort;

    @Value("${tsywxt-config.nio.listener.udp-port}")
    public String udpPort;

    @Value("${rockdb-config.save-path}")
    public String rockdbSavePath;

    @Value("${mq-topic.topic-queue-waiting-process-datagram}")
    public String tsV1DatagramTopic;

    @Resource
    public RedisTemplate redisTemplate;

    static {
        RocksDB.loadLibrary();
    }

    public void putStoreCache(String key, String content) throws UnsupportedEncodingException, RocksDBException {
        this.storeCache.put(key.getBytes("utf-8"), content.getBytes("utf-8"));
    }

    public byte[] getStoreCache(String key) throws UnsupportedEncodingException, RocksDBException {
        return this.storeCache.get(key.getBytes("utf-8"));
    }

    @PostConstruct
    public void init() {
        log.info("************************************* " + serverName + "  服务启动 *************************************");
        try {
            log.info("初始化ROCKDB{}", rockdbSavePath);
            this.storeCache = RocksDB.open(rockdbSavePath);
            //写入运行参数
            String key = "topic." + KafkaConstants.TOPIC_TS_V1_DATAGRAM;
            this.putStoreCache(key, KafkaConstants.TOPIC_TS_V1_DATAGRAM);

            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(new StringRedisSerializer());

            log.info("初始化报文模板配置模块");
            MainProcessorHolder.newInstance().dataProcess = this;
            DataTemplateManager dataTemplateManager = new DataTemplateManager();
            dataTemplateManager.init(templatesDirPath, templates);
            DataTemplateManageHolder.newInstance().dataTemplateManager = dataTemplateManager;
            log.info("初始化网络通道模块");
            DataChannel dataChannel = new DataChannel();
            if (null != tcpPort && tcpPort.length() > 0) {
                String[] ports = tcpPort.split(",");
                for (String set : ports) {
                    String[] sets = set.split("-");
                    String port = sets[0].trim().toLowerCase();
                    String active = sets[1].trim().toUpperCase();
                    if (NetPortStatusConstant.ON.equals(active)) {
                        log.info("启动TCP通道 端口： {} ", port);
                        dataChannel.addTcpChannel(Integer.parseInt(port));
                    }
                }
            }
            if (null != udpPort && udpPort.length() > 0) {
                String[] ports = udpPort.split(",");
                for (String set : ports) {
                    String[] sets = set.split("-");
                    String port = sets[0].trim().toLowerCase();
                    String active = sets[1].trim().toUpperCase();
                    if (NetPortStatusConstant.ON.equals(active)) {
                        log.info("启动UDP通道 端口： {}", port);
                        dataChannel.addUdpChannel(Integer.parseInt(port));
                    }
                }
            }
            DataChannelHolder.newInstance().dataChannel = dataChannel;
            log.info("初始化数据流处理模块");
            DataStreamManager dataStreamManager = new DataStreamManager();
            DataStreamManageHolder.newInstance().dataStreamManager = dataStreamManager;
            dataStreamManager.init(this.templates, this.storeCache);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
//            String[] args = new String[]{"1","2"};
//            ConfigurableApplicationContext context = SpringApplication.run(DataCollectApplication.class, args);
//            context.close();

//            int exitCode = SpringApplication.exit(DataCollectApplication.configurableApplicationContext, new ExitCodeGenerator() {
//                @Override
//                public int getExitCode() {
//                    // no errors
//                    return 0;
//                }
//            });
//            System.exit(exitCode);
        } finally {
            log.info("************************************* " + serverName + " 服务已成功运行 *************************************");
        }
    }

    public void submitTask(FutureTask<Integer> task) {
        publicThreadPool.execute(task);
    }


}
