package com.ruoyi.system.core.deviceEntity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.system.core.ClientExecute;
import com.ruoyi.system.core.annotate.DeviceEntity;
import com.ruoyi.system.core.domain.DeviceFunc;
import com.ruoyi.system.core.mqtt.DefProtocol;
import com.ruoyi.system.core.mqtt.MqttFuncTopic;
import com.ruoyi.system.core.mqtt.ReplyPackage;
import com.ruoyi.system.domain.SysDevice;
import com.ruoyi.system.domain.SysDeviceProperty;
import com.ruoyi.system.domain.SysDeviceStatus;
import com.ruoyi.system.mapper.SysDeviceMapper;
import com.ruoyi.system.mapper.SysDeviceStatusMapper;
import com.ruoyi.system.service.ISysDevicePropertyService;
import com.ruoyi.system.util.SpringContextHolder;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@DeviceEntity(product = "SF")
@Component
public class SdSj implements ProductEntity{
    @Override
    public void put(DefProtocol defProtocol, ClientExecute clientExecute, SysDevice device) {
        try {
            // 使用getMethod查找公有方法
            Method method = this.getClass().getMethod(defProtocol.getFunctionId(), DefProtocol.class, ClientExecute.class, SysDevice.class);
            method.invoke(this, defProtocol, clientExecute, device); // 执行该方法
        } catch (NoSuchMethodException e) {
            // 找不到对应方法时，执行commonPut方法
            commonPut(defProtocol, clientExecute, device);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("Failed to invoke the method", e);
        }
    }

    @Override
    public void info(DefProtocol defProtocol, ClientExecute clientExecute, SysDevice device) {
        try {
            // 使用getMethod查找公有方法
            Method method = this.getClass().getMethod(defProtocol.getFunctionId(), DefProtocol.class, ClientExecute.class, SysDevice.class);
            method.invoke(this, defProtocol, clientExecute, device); // 执行该方法
        } catch (NoSuchMethodException e) {
            // 找不到对应方法时，执行commonPut方法
            commonPut(defProtocol, clientExecute, device);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("Failed to invoke the method", e);
        }
    }

    public void control(DefProtocol defProtocol, ClientExecute clientExecute, SysDevice device){
        SysDeviceStatusMapper statusMapper = SpringContextHolder.getBean(SysDeviceStatusMapper.class);
        statusMapper.selectByFunctionId(defProtocol.getFunctionId())
                .switchIfEmpty(statusMapper.insert(new SysDeviceStatus(defProtocol)).thenReturn(new SysDeviceStatus(defProtocol)))
                .subscribe(x -> {
                    if (x.getDeviceStatusId() != null) {
                        x.setInputs(defProtocol.getInputs());
                        statusMapper.update(x).subscribe();
                    }
                    DeviceFunc deviceFunc = new DeviceFunc();
                    deviceFunc.setFuncTopic(MqttFuncTopic.REPLY);
                    deviceFunc.setMessage(new ReplyPackage(x, defProtocol).getInputs());
                    clientExecute.send(device, deviceFunc);
                    JSONArray objects = JSON.parseArray(defProtocol.getInputs());
                    List<SysDeviceProperty> properties = new ArrayList<>();
                    for (int i = 0; i < objects.size(); i++) {
                        JSONObject jsonObject = objects.getJSONObject(i);
                        SysDeviceProperty sysDeviceProperty = new SysDeviceProperty();
                        sysDeviceProperty.setValue(jsonObject.getString("value"));
                        sysDeviceProperty.setFuncId(defProtocol.getFunctionId());
                        sysDeviceProperty.setName(jsonObject.getString("name"));
                        sysDeviceProperty.setValueCalss(jsonObject.get("value").getClass().toString());
                        sysDeviceProperty.setDeviceType(device.getDeviceType());
                        properties.add(sysDeviceProperty);
                    }
                    ISysDevicePropertyService propertyService = SpringContextHolder.getBean(ISysDevicePropertyService.class);
                    propertyService.sync(device, properties, x.getFunctionId()).subscribe();
                    SysDeviceMapper deviceMapper = SpringContextHolder.getBean(SysDeviceMapper.class);
                    deviceMapper.update(device).subscribe();
                });
    }
}
