package com.utic.center.utic.traf.server;

import com.utic.center.common.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

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

@Slf4j
//@SpringBootTest
public class UticTrafServerApplicationTests {

    @Test
    void travelTime() {
        int length = 441;
        int speed = 17; // km/h
        int travelTime =  Math.max(2, Math.round((length * 36) / (float)(speed * 10)));
        log.info("Travel Time: {}", travelTime);
    }
    @Test
    void arrayTest() {
        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
        int THREAD_POOL_SIZE = 3;
        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
            int startIdx = i * batchPerThread;
            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);

            String[] subArray = Arrays.copyOfRange(linkIds, startIdx, endIdx);
            log.info("Thread {}: {}", i, Arrays.toString(subArray));
        }
    }
    @Test
    void arrayTest2() {
        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
        int THREAD_POOL_SIZE = 3;
        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
            int startIdx = i * batchPerThread;
            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);

            String[] subArray = new String[endIdx - startIdx];
            System.arraycopy(linkIds, startIdx, subArray, 0, endIdx - startIdx);
            log.info("Thread {}: {}", i, Arrays.toString(subArray));
        }

    }
    @Test
    void arrayTest3() {
        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
        int THREAD_POOL_SIZE = 3;
        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
            int startIdx = i * batchPerThread;
            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);

            String[] subArray = new String[endIdx - startIdx];
            System.arraycopy(linkIds, startIdx, subArray, 0, endIdx - startIdx);
            log.info("Thread {}: {}", i, Arrays.toString(subArray));
        }

    }

    @Test
    void testDecompress() {
        String dateTimeStr = "20240512000000";
        for (int ii = 0; ii < 62; ii++) {
            String currTime = TimeUtils.addMinutes(dateTimeStr, ii);
            String nextTime = TimeUtils.addMinutes(currTime, 5);
            String nextPrcsTime = TimeUtils.getFiveMinString(TimeUtils.stringToDate(nextTime));
            String patternTime = TimeUtils.roundToQuarterHour(nextPrcsTime);
            log.info("Original: {}/{}/{} => {}", currTime, nextTime, nextPrcsTime, patternTime);
//            String roundedTime = TimeUtils.roundToQuarterHour(prcsTime);
//            String quaterTime = TimeUtils.getQuarterHour(prcsTime);
//            log.info("Original: {}/{}, => {}/{}, {}", currTime, prcsTime, roundedTime, quaterTime, roundedTime.equals(quaterTime));
        }
    }


    @Test
    void tt() {
        String patternTime = "20250513162500";
        String patternHourMin = patternTime.substring(8, 12);
        log.info("patternTime: {}, patternHourMin: {}", patternTime, patternHourMin);
    }
    @Test
    void testDecompress2010() {
        //ReadableBytes: 113 Bytes
        String data = "02C518081901061911551DB1020C000200010200030036E04BC31020DDC10105E021C11020E030C80102D8C10105C2C10105E039C8010200555C9C2503000102090F3C090F3C010C1246006C2400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010201030025E041C80102E0B7C80102E021C5102000555C9C2503000102090F3C090F3C01040546003E450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AB03";
    }


    @Test
    void test() {
        //1720599437901
        //1720599437
        //106844625303900
        final long start = System.currentTimeMillis();
        log.error("[{}, {}, {}]", start, TimeUnit.SECONDS.convert(start, TimeUnit.MILLISECONDS), System.nanoTime());
    }

    @Test
    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();
        }
    }

    static 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();
                }
            }
        }
    }

    static class NamedThreadsFactory implements ThreadFactory {

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

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, Name + ++count);
        }
    }

    @Test
    void testThread() {
        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);
                    }
                }
            });*/
        }
    }

}