package com.example.iot_controlhost.utils.control.ventilator;

import com.example.iot_controlhost.model.thread.QueueIOTask;
import com.example.iot_controlhost.utils.MyQueue;
import com.example.iot_controlhost.utils.MyUtil;
import com.example.iot_controlhost.utils.PollingTask;
import com.example.iot_controlhost.utils.control.Control;
import com.example.iot_controlhost.utils.global.AIModelSet;
import com.example.iot_controlhost.utils.global.AutoModelSet;
import com.example.iot_controlhost.utils.global.RoomController;
import com.example.iot_controlhost.utils.global.RoomSetting;
import com.example.iot_controlhost.utils.global.RxTag;
import com.example.iot_controlhost.utils.global.SpinnerList;
import com.example.iot_controlhost.utils.log.MyLog;

/**
 * @Description 自动模式下换气扇控制
 * @Author DuanKaiji
 * @CreateTime 2023年11月09日 10:26:30
 */
public class VentilatorController extends Control {
    /**
     * 开启持续时间
     */
    int targetOpen;
    /**
     * 关闭持续时间
     */
    int targetClose;
    /**
     * 调度代次。参数重载或停止后，旧任务即使已经进入执行阶段也不能继续串接新任务。
     */
    private volatile long scheduleGeneration;

    /**
     * 单例模式
     */
    private static VentilatorController instance;

    public static VentilatorController getInstance() {
        if (instance == null) {
            synchronized (VentilatorController.class) {
                if (instance == null) {
                    instance = new VentilatorController();
                }
            }
        }
        return instance;
    }

    @Override
    protected boolean startMethod() {
        //每次开启时获取最新参数
        refreshRule();
        if (!RoomController.fan.isAvailable()) {
            MyLog.autoError("换气自动控制无法启动：换气扇不可用");
            return false;
        }
        MyLog.auto("换气自动控制初始化：先关闭换气扇，开启时长=" + targetOpen
                + "分钟，关闭时长=" + targetClose + "分钟");
        long generation = ++scheduleGeneration;
        stopFan(0, generation);
        return true;
    }

    private void refreshRule() {
        if (RoomSetting.getMode() == 1) {
            targetOpen = AutoModelSet.getCycleStart();
            targetClose = AutoModelSet.getCycleStop();
        } else if (RoomSetting.getMode() == 2) {
            targetOpen = AIModelSet.getAiCycleStart();
            targetClose = AIModelSet.getAiCycleStop();
        }
    }

    private void startFan(int minutes, long generation) {
        PollingTask activePollingTask = pollingTask;
        if (generation != scheduleGeneration || activePollingTask == null) {
            MyLog.auto("换气旧任务不再创建开启调度：任务代次=" + generation
                    + "，当前代次=" + scheduleGeneration);
            return;
        }
        MyLog.auto("换气调度：计划" + minutes + "分钟后开启换气扇");
        activePollingTask.startDelayedTask(RxTag.VENTILATOR_AUTO_START_FUN, minutes * 60, () -> {
            try {
                if (generation != scheduleGeneration) {
                    MyLog.auto("换气旧任务已失效，取消开启阶段：任务代次=" + generation
                            + "，当前代次=" + scheduleGeneration);
                    return;
                }
                refreshRule();
                if (targetOpen == 0 && targetClose == 0) {
                    //如果开始停止时间均为0，则3分钟后再次检测配置项
                    MyLog.auto("换气控制暂停：开启和关闭时长均为0，3分钟后重新读取配置");
                    startFan(3, generation);
                    return;
                }
                // 开启换气扇
                MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
                    if (generation != scheduleGeneration) {
                        MyLog.auto("换气旧任务已失效，取消已入队的开启操作：任务代次=" + generation);
                        return;
                    }
                    String airExchangeMode = AutoModelSet.getAirExchangeMode();
                    boolean fanResult;
                    if (RoomController.fan.hasAvailableFanForCurrentMode()) {
                        fanResult = MyUtil.autoControlOperateThird(RoomController.fan, true);
                    } else {
                        fanResult = false;
                        MyLog.autoError("换气控制无法开启：模式=" + AutoModelSet.getVentilatorMode()
                                + "，进气扇可用=" + RoomController.intakeFan.isAvailable()
                                + "，端口=" + RoomController.intakeFan.getPorts()
                                + "；排气扇可用=" + RoomController.exhaustFan.isAvailable()
                                + "，端口=" + RoomController.exhaustFan.getPorts());
                    }
                    MyLog.auto("换气控制执行结果：设备=换气扇，目标=开启，结果="
                            + (fanResult ? "成功" : "失败") + "，计划运行=" + targetOpen + "分钟");
                    if (RoomController.airExchange.isAvailable() && airExchangeMode.equals(SpinnerList.AIR_EXCHANGE_MODES[1])) {
                        boolean airExchangeResult = MyUtil.autoControlOperateThird(RoomController.airExchange, true);
                        MyLog.auto("换气联动执行结果：设备=新风，目标=开启，结果="
                                + (airExchangeResult ? "成功" : "失败"));
                    }
                }));
                MyLog.auto("换气调度：计划" + targetOpen + "分钟后关闭换气扇");
                stopFan(targetOpen, generation);
            } catch (Throwable throwable) {
                MyLog.autoError("换气扇开启阶段异常：异常=" + throwable.getClass().getSimpleName()
                        + "，原因=" + throwable.getMessage() + "，1分钟后尝试恢复调度");
                if (generation == scheduleGeneration) {
                    startFan(1, generation);
                }
            }
        });
    }

    /**
     * 关闭风扇
     *
     * @param minutes 该时间后检测下一步动作
     */
    private void stopFan(int minutes, long generation) {
        PollingTask activePollingTask = pollingTask;
        if (generation != scheduleGeneration || activePollingTask == null) {
            MyLog.auto("换气旧任务不再创建关闭调度：任务代次=" + generation
                    + "，当前代次=" + scheduleGeneration);
            return;
        }
        // 开启换气扇，持续targetOpen分钟
        activePollingTask.startDelayedTask(RxTag.VENTILATOR_AUTO_STOP_FUN, minutes * 60, () -> {
            try {
                if (generation != scheduleGeneration) {
                    MyLog.auto("换气旧任务已失效，取消关闭阶段：任务代次=" + generation
                            + "，当前代次=" + scheduleGeneration);
                    return;
                }
                refreshRule();
                // 关闭换气扇
                MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
                    if (generation != scheduleGeneration) {
                        MyLog.auto("换气旧任务已失效，取消已入队的关闭操作：任务代次=" + generation);
                        return;
                    }
                    if (RoomController.airExchange.isAvailable() && AutoModelSet.getAirExchangeMode().equals(SpinnerList.AIR_EXCHANGE_MODES[1])) {
                        boolean airExchangeResult = MyUtil.autoControlOperateThird(RoomController.airExchange, false);
                        MyLog.auto("换气联动执行结果：设备=新风，目标=关闭，结果="
                                + (airExchangeResult ? "成功" : "失败"));
                    }
                    boolean fanResult = MyUtil.autoControlOperateThird(RoomController.fan, false);
                    MyLog.auto("换气控制执行结果：设备=换气扇，目标=关闭，结果="
                            + (fanResult ? "成功" : "失败") + "，计划停运=" + targetClose + "分钟");
                }));
                startFan(targetClose, generation);
            } catch (Throwable throwable) {
                MyLog.autoError("换气扇关闭阶段异常：异常=" + throwable.getClass().getSimpleName()
                        + "，原因=" + throwable.getMessage() + "，1分钟后尝试恢复调度");
                if (generation == scheduleGeneration) {
                    startFan(1, generation);
                }
            }
        });
    }

    /**
     * 启停时长或分路模式变化后，废弃旧计时并从关闭阶段按新规则重新建立周期。
     */
    public synchronized void reloadSchedule(String source) {
        int previousOpen = targetOpen;
        int previousClose = targetClose;
        boolean wasRunning = isRunning();
        refreshRule();

        if (RoomSetting.getMode() == 1 && !AutoModelSet.isAutoVentilator()) {
            MyLog.auto("换气调度重载：来源=" + source + "，自动换气已关闭，停止现有任务");
            stop();
            return;
        }
        if (!wasRunning) {
            if (RoomSetting.getMode() == 1 && AutoModelSet.isAutoVentilator()) {
                MyLog.auto("换气调度重载：来源=" + source + "，控制器未运行，按最新参数启动；开启="
                        + targetOpen + "分钟，关闭=" + targetClose + "分钟");
                start();
            } else {
                MyLog.auto("换气参数已更新但控制器当前未运行：来源=" + source + "，开启="
                        + targetOpen + "分钟，关闭=" + targetClose + "分钟");
            }
            return;
        }

        long invalidGeneration = ++scheduleGeneration;
        if (pollingTask != null) {
            pollingTask.stopAllPollingTasks();
        }
        pollingTask = null;
        start = false;
        MyLog.auto("换气调度重载：来源=" + source + "，开启=" + previousOpen + "→" + targetOpen
                + "分钟，关闭=" + previousClose + "→" + targetClose + "分钟，模式="
                + AutoModelSet.getVentilatorMode() + "，失效标记=" + invalidGeneration + "，旧任务已取消");
        start();
    }

    @Override
    protected void stopMethod() {
        scheduleGeneration++;
        MyLog.auto("停止自动控制换气————————————————————————————————————————————————————");
        MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
            MyUtil.autoControlOperateThird(RoomController.fan);
            if (RoomController.airExchange.isAvailable() && AutoModelSet.getAirExchangeMode().equals(SpinnerList.AIR_EXCHANGE_MODES[1])) {
                MyUtil.autoControlOperateThird(RoomController.airExchange, false);
            }
        }));
    }
}
