package com.tsi.comm.server;

import com.tsi.comm.server.protocol.TsiCpuPacket;
import com.tsi.common.utils.ByteUtils;
import com.tsi.common.utils.CRC16Utils;
import com.tsi.common.utils.HexString;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
//@SpringBootTest
public class TsiCommServerApplicationTests {

    //@Test
    void contextLoads() {
    }

    @Test
    public void test1() {
        String hostName;
        String hostAddress;
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            hostName = localhost.getHostName();
            hostAddress = localhost.getHostAddress();
        } catch (UnknownHostException e) {
            hostName = "localhost";
            hostAddress = "127.0.0.1";
        }
        System.out.println("Your current IP address : " + hostAddress);
        System.out.println("Your current Hostname : " + hostName);

        InetAddress ip;
        String hostname;
        try {
            ip = InetAddress.getLocalHost();
            hostname = ip.getHostName();
            System.out.println("Your current IP address : " + ip);
            System.out.println("Your current Hostname : " + hostname);

        } catch (UnknownHostException e) {

            e.printStackTrace();
        }
    }
    class WorkerThreadTask implements Runnable {

        private ThreadPoolExecutor processExecutor;

        public WorkerThreadTask(ThreadPoolExecutor processExecutor, int idx) {
            Thread.currentThread().setName(String.format("worker-pool-%02d", idx));
            this.processExecutor = processExecutor;
        }

        @Override
        public void run() {
            while (true) {
                log.error("{}, corePoolSize: {}, activeCount: {}, maximumPoolSize: {}, poolSize: {}, taskCount: {}",
                        Thread.currentThread().getName(),
                        processExecutor.getCorePoolSize(),
                        processExecutor.getActiveCount(),
                        processExecutor.getMaximumPoolSize(),
                        processExecutor.getPoolSize(),
                        processExecutor.getTaskCount());
                try {
                    Thread.sleep(1000);
                    if (processExecutor.awaitTermination(1L, TimeUnit.MILLISECONDS))
                        log.info("Terminated");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    class NamedThreadsFactory implements ThreadFactory {

        private int count = 0;
        private String Name = "MyThread-";

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, Name + ++count); // Mythread-x 형태로 쓰레드 이름 설정
        }
    }

    @Test
    public void testThread() throws InterruptedException {
        int threadPoolSize = Runtime.getRuntime().availableProcessors() * 10;
        ThreadPoolExecutor processExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        log.info("corePoolSize: {}, activeCount: {}, maximumPoolSize: {}, poolSize: {}, taskCount: {}",
                processExecutor.getCorePoolSize(),
                processExecutor.getActiveCount(),
                processExecutor.getMaximumPoolSize(),
                processExecutor.getPoolSize(),
                processExecutor.getTaskCount());

        for (int ii = 0; ii < threadPoolSize; ii++) {
            log.info("Thread Start: {}", ii);
            processExecutor.execute(new WorkerThreadTask(processExecutor, ii));
            /*processExecutor.execute(() -> {
                while (true) {
                    try {
                        log.error("{}, corePoolSize: {}, activeCount: {}, maximumPoolSize: {}, poolSize: {}, taskCount: {}",
                                Thread.currentThread().getName(),
                                processExecutor.getCorePoolSize(),
                                processExecutor.getActiveCount(),
                                processExecutor.getMaximumPoolSize(),
                                processExecutor.getPoolSize(),
                                processExecutor.getTaskCount());
                        Thread.sleep(1000);
                    }
                    catch (Exception e) {
                        log.error("{}", e.getMessage(), e);
                    }
                }
            });*/
        }
        Thread.sleep(20000);
    }

    @Test
    public void checkSumTest() {
        long nodeId = 110000001;
        String strHex = "7E7E004E1301068E77810002310C60F1375E10CB280B0A20CB321F0A30CB320D0A10CA03011420CA32011430CA322B1410C9280B1E20C9321F1E30C9320D1E10C903012820C928012830C9282B28FD89";
        byte[] packet = ByteUtils.hexToByteArray(strHex);
        log.error("{}", HexString.fromBytes(packet));
        int dataLength = ByteUtils.getUnsignedShort(packet, TsiCpuPacket.INDEX_LENGTH);
        log.error("dataLength: {}, packetLength: {}", dataLength, packet.length);
        int recvCheckSum = ByteUtils.getUnsignedShort(packet, packet.length-2);
        int calcCheckSum = CRC16Utils.CRC16_ccitt_cvim(packet, 2, dataLength-2);
        if (recvCheckSum != calcCheckSum) {
            log.info("Node: {}, Check Sum Error: {},{}, recv: {}, calc: {}", nodeId, 0xFD89, 0x89FD, recvCheckSum, calcCheckSum);
        }
        else {
            log.info("Node: {}, Check Sum OK: recv: {}, calc: {}", nodeId, recvCheckSum, calcCheckSum);
        }
    }

}
