package com.ruoyi.system.core.scnner;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.system.core.ClientExecute;
import com.ruoyi.system.core.ClientExecuteFactory;
import com.ruoyi.system.core.DeviceStatus;
import com.ruoyi.system.core.domain.DataStrategy;
import com.ruoyi.system.core.domain.DeviceFunc;
import com.ruoyi.system.core.mqtt.MqttFuncTopic;
import com.ruoyi.system.core.mqtt.MqttPackage;
import com.ruoyi.system.core.mqtt.ReplyPackage;
import com.ruoyi.system.domain.SysDevice;
import com.ruoyi.system.domain.SysDeviceProperty;
import com.ruoyi.system.forward.mq.MqttProducerService;
import com.ruoyi.system.service.ISysDevicePropertyService;
import com.ruoyi.system.service.ISysDeviceService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component("heartbeat")
public class Report {
    @Resource
    private ISysDeviceService deviceService;
    @Resource
    private ClientExecuteFactory factory;
    @Resource
    private ISysDevicePropertyService devicePropertyService;
    @Resource
    private MqttProducerService mqttProducerService;

    public static List<DataStrategy> dataStrategies = new ArrayList<>();

    static {
        DataStrategy flow_count = new DataStrategy();
        flow_count.setDeviceType("JP");
        flow_count.setKey("flow_count");
        flow_count.setModel(DataStrategy.RANDOM_MODEL);
        flow_count.setFloatNum(200);
        flow_count.setDefData(2200);
        dataStrategies.add(flow_count);

        DataStrategy water_pressure = new DataStrategy();
        water_pressure.setDeviceType("JP");
        water_pressure.setKey("water_pressure");
        water_pressure.setModel(DataStrategy.RANDOM_MODEL);
        water_pressure.setFloatNum(10);
        water_pressure.setDefData(45);
        dataStrategies.add(water_pressure);

        DataStrategy runtime = new DataStrategy();
        runtime.setDeviceType("JP");
        runtime.setKey("runtime");
        runtime.setModel(DataStrategy.RANDOM_MODEL);
        runtime.setFloatNum(40);
        runtime.setDefData(249);
        dataStrategies.add(runtime);

//        DataStrategy speed = new DataStrategy();
//        speed.setDeviceType("JP");
//        speed.setKey("speed");
//        speed.setModel(DataStrategy.RANDOM_MODEL);
//        speed.setFloatNum(40);
//        speed.setDefData(249);
//        dataStrategies.add(speed);
    }

    public void run() {
        SysDevice device = new SysDevice();
        device.setStatus(DeviceStatus.ONLINE);
        device.setEnable(true);
        deviceService.selectList(device).subscribe(devices -> {
            for (SysDevice sysDevice : devices) {
                SysDeviceProperty query = new SysDeviceProperty();
                query.setDeviceType(sysDevice.getDeviceType());
                devicePropertyService.selectList(query).subscribe(properties -> {
                    List<String> funcIds = properties.stream().map(SysDeviceProperty::getFuncId).distinct().collect(Collectors.toList());
                    ClientExecute clientExecute = factory.getClientExecute(sysDevice.getConnectionType());
                    JSONObject reportObj = new JSONObject();
                    for (String funcId : funcIds) {
                        List<SysDeviceProperty> collect = properties.stream().filter(x -> x.getFuncId().equals(funcId)).collect(Collectors.toList());
                        for (SysDeviceProperty sysDeviceProperty : collect) {
                            this.setProperty(sysDeviceProperty, reportObj, sysDevice.getDeviceType());
                        }
                    }
                    DeviceFunc deviceFunc = new DeviceFunc();
                    deviceFunc.setMessage(reportObj.toJSONString());
                    deviceFunc.setFuncTopic(MqttFuncTopic.REPORT);
                    clientExecute.send(sysDevice, deviceFunc);
                    mqttProducerService.send("/" + sysDevice.getDeviceType() + "/" + sysDevice.getDeviceNo() + "/" + deviceFunc.getFuncTopic().getValue(), JSON.toJSONString(new MqttPackage(device.getDeviceNo(), JSON.parseObject(deviceFunc.getMessage()))));

                });
            }
        });
    }

    private void setProperty(SysDeviceProperty deviceProperty, JSONObject reportObj, String deviceType) {
        if (deviceProperty.getName().equals("time")) {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String format = df.format(date);
            reportObj.put(deviceProperty.getName(), format);
            return;
        }
        Optional<DataStrategy> first = dataStrategies.stream().filter(x -> x.getKey().equals(deviceProperty.getName()) && x.getDeviceType().equals(deviceType)).findFirst();
        if (!first.isPresent()) {
            reportObj.put(deviceProperty.getName(), deviceProperty.getValue());
            return;
        }
        if (first.get().getModel().equals(DataStrategy.RANDOM_MODEL)) {
            reportObj.put(deviceProperty.getName(), generateRandomValue(first.get().getDefData(), first.get().getFloatNum()));
            return;
        }

    }

    public int generateRandomValue(int baseValue, int fluctuation) {
        Random random = new Random();
        int minValue = baseValue - fluctuation;
        int maxValue = baseValue + fluctuation;
        return random.nextInt((maxValue - minValue) + 1) + minValue;
    }

}
