package org.nl.acs.opc;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.auto.run.AbstractAutoRunnable;
import org.nl.acs.device_driver.driver.ExecutableDeviceDriver;
import org.nl.config.thread.TheadFactoryName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author 20220102CG\noblelift
 */
@Component
@Slf4j
@Lazy
public class DeviceExecuteAutoRun extends AbstractAutoRunnable {
    @Autowired
    DeviceAppService deviceAppService;
    int cache_thread = 3;

    int corePoolSize = 50;
    int maximumPoolSize = 100;
    int queueLength = maximumPoolSize * cache_thread;

    int multiple = cache_thread;

    int loop_time_millions = 100;
    ExecutorService executorService;
    Map<String, BlockedRunable> runs;

    public DeviceExecuteAutoRun() {
        // this.executorService = Executors.newCachedThreadPool();
      /*  this.executorService=new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                1L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>( queueLength),
                new TheadFactoryName()
        );*/
        this.executorService = new ThreadPoolExecutor(
                10,
                20,
                1L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(queueLength),
                new TheadFactoryName(), new RejectedExecutionHandler() {

            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                if (!executor.isShutdown()) {
                    try {
                        executor.getQueue().put(r);
                    } catch (InterruptedException arg3) {
                        log.debug("", arg3);
                    }
                }
            }
        }
        );
        this.runs = new LinkedHashMap();
        this.runs = Collections.synchronizedMap(this.runs);
    }

    @Override
    public String getCode() {
        return DeviceExecuteAutoRun.class.getSimpleName();
    }


    @Override
    public String getName() {
        return "设备执行线程";
    }

    @Override
    public void autoRun() throws Exception {
        //todo 执行每个设备的excute
        for (int i = 0; !OpcStartTag.is_run; ++i) {
            log.info("设备执行线程等待opc同步线程...");
            Thread.sleep(1000L);
            if (i > 60) {
                log.info("设备执行线程放弃等待opc同步线程...");
                break;
            }
        }

        log.info("设备执行线程开始...");

        while (true) {
            try {
                Thread.sleep((long) this.loop_time_millions);
                List<ExecutableDeviceDriver> deviceDrivers = this.deviceAppService.findDeviceDriver(ExecutableDeviceDriver.class);
                Iterator it = deviceDrivers.iterator();
                while (it.hasNext()) {
                    final ExecutableDeviceDriver deviceDriver = (ExecutableDeviceDriver) it.next();
                    //不包含正在执行的线程，则进行执行
                    if (!this.runs.keySet().contains(deviceDriver.getDeviceCode())) {
                        BlockedRunable runnable = new BlockedRunable() {
                            @Override
                            public void subRun() throws Exception {
                                deviceDriver.executeAuto();
                            }

                            @Override
                            public String getCode() {
                                return deviceDriver.getDeviceCode();
                            }
                        };
                        if (!this.runs.keySet().contains(deviceDriver.getDeviceCode())) {
                            this.runs.put(deviceDriver.getDeviceCode(), runnable);
                        }

                        runnable.setIndex(this.runs);
                        this.executorService.submit(runnable);
                    }
                }
            }catch (Exception e){
                log.info("设备执行线程失败DeviceExecuteAutoRun:{}{}",e,e.getMessage());
            }
        }
    }
}
