package com.yuchen.saas.park.api.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.thinkunion.park.service.common.cache.CacheNames;
import com.yuchen.saas.park.api.enums.IotProductEnum;
import com.yuchen.saas.park.api.vo.park.devicepro.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.nest.springwrap.core.redis.cache.NestRedis;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author: 肖润飞
 * @CreateTime: 2022/09/13 14:37
 * @Description: 根据设备的productKey 从redis中获得最新的设备缓存数据
 * @Version: 1.0
 */
@Slf4j
@Component
public class DeviceDataUtils {

    @Resource
    private NestRedis nestRedis;

    /**
     * 根据设备的productKey 从redis中获得最新的设备缓存数据
     *
     * @param productKey 设备种类key
     * @return
     */
    public List<DeviceBasePro> getDeviceDataFromCash(String productKey, String parkId) {
        log.info("需要获得的最新设备数据 productKey = {}", productKey);
        StringBuilder prefixKey = new StringBuilder(CacheNames.DEVICE_PRO_PREFIX).append(parkId).append(":").append(productKey);
        // 单个设备统计数据的集合
        List<DeviceBasePro> deviceList = new ArrayList<>();
        // 根据指定prefixKey 获得 key_set ,这里建议用scan , 需要在nestRedis封装该方法
        Set<String> keys = nestRedis.keys(prefixKey.append(":*").toString());
        log.info("keys = {}", keys);
        // 循环key_set,根据key获得指定hash_key的值,并处理
        keys.forEach(cashKey -> {
            log.info("cashKey = {}", cashKey);
            Map cashMap = nestRedis.hGetAll(cashKey);
            if (MapUtil.isEmpty(cashMap)) {
                return;
            }
            String clazzStr = (String) cashMap.get("clazz");
            log.info("clazzStr = {}", clazzStr);
            if (StringUtils.isNotBlank(clazzStr)) {
                if (clazzStr.startsWith("com.thinkunion")) {
                    // 设置新的clazz
                    String newClazz = this.changeClazz(productKey);
                    log.info("newClazz = {}", newClazz);
                    if (StrUtil.isNotBlank(newClazz)) {
                        //缓存中色设置新的clazz
                        nestRedis.hSet(cashKey, "clazz", newClazz);
                        clazzStr = newClazz;
                    }
                }
                Class<?> clazz = null;
                try {
                    clazz = Class.forName(clazzStr);
                    log.info("clazz = {}", clazz);
                    DeviceBasePro deviceBasePro = (DeviceBasePro) BeanUtil.toBean(cashMap, clazz);
                    // 未计算数据
                    deviceList.add(deviceBasePro);
                } catch (ClassNotFoundException e) {
                    log.error("将缓存设备数据map转换成bean失败,找不到指定的类 : {}", e.getMessage());
                    throw new RuntimeException(e);
                }
            }
        });
        return deviceList;
    }

    public List<Map<String, Object>> getDeviceMapFromCash(String productKey, String parkId) {
        List<Map<String, Object>> resList = new ArrayList<>();
        log.info("需要获得的最新设备数据 productKey = {}", productKey);
        StringBuilder prefixKey = new StringBuilder(CacheNames.DEVICE_PRO_PREFIX).append(parkId).append(":").append(productKey);
        // 根据指定prefixKey 获得 key_set ,这里建议用scan , 需要在nestRedis封装该方法
        Set<String> keys = nestRedis.keys(prefixKey.append(":*").toString());
        // 循环key_set,根据key获得指定hash_key的值,并处理
        keys.forEach(cashKey -> {
            Map cashMap = nestRedis.hGetAll(cashKey);
            resList.add(cashMap);
        });
        return resList;
    }

    /**
     * 获取单个设备的数据
     *
     * @param parkId     园区ID
     * @param productKey 设备 productKey
     * @param deviceName 设备 deviceName
     * @return
     */
    public DeviceBasePro getDeviceInfoFromCash(String parkId, String productKey, String deviceName) {
        log.info("需要获得的最新设备数据 productKey = {} deviceName = {}", productKey, deviceName);
        StringBuilder prefixKey = new StringBuilder(CacheNames.DEVICE_PRO_PREFIX).append(parkId).append(":").append(productKey);
        // 单个设备统计数据的集合
        DeviceBasePro deviceBasePro = new DeviceBasePro();
        // 根据指定prefixKey 获得 key_set ,这里建议用scan , 需要在nestRedis封装该方法
        Set<String> keys = nestRedis.keys(prefixKey.append(":*").toString());
        // 循环key_set,根据key获得指定hash_key的值,并处理
        for (String cashKey : keys) {
            Map cashMap = nestRedis.hGetAll(cashKey);
            if (MapUtil.isEmpty(cashMap)) {
                break;
            }
            if (cashMap.get("productKey").equals(productKey) && cashMap.get("deviceName").equals(deviceName)) {
                String clazzStr = (String) cashMap.get("clazz");
                if (StringUtils.isNotBlank(clazzStr)) {
                    if (clazzStr.startsWith("com.thinkunion")) {
                        // 设置新的clazz
                        String newClazz = this.changeClazz(productKey);
                        if (StrUtil.isNotBlank(newClazz)) {
                            //缓存中色设置新的clazz
                            nestRedis.hSet(cashKey, "clazz", newClazz);
                            clazzStr = newClazz;
                        }
                    }
                    Class<?> clazz = null;
                    try {
                        clazz = Class.forName(clazzStr);
                        deviceBasePro = (DeviceBasePro) BeanUtil.toBean(cashMap, clazz);
                    } catch (ClassNotFoundException e) {
                        log.error("将缓存设备数据map转换成bean失败,找不到指定的类 : {}", e.getMessage());
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return deviceBasePro;
    }


    /**
     * 根据园区id, 获得设备总数
     *
     * @return 指定园区的设备总数
     */
    public int getDeviceTotal(String parkId) {
        String key = new StringBuilder(CacheNames.DEVICE_PRO_PREFIX).append(parkId).append(":*").toString();
        Set<String> keys = nestRedis.keys(key);
        if (keys != null) {
            return keys.size();
        }
        return 0;
    }

    /**
     * @return
     */
    private String changeClazz(String productKey) {
        String result = "";
        if (productKey.equals(IotProductEnum.WATER_PRESSURE_DEVICE.getValue())) {
            result = WaterPressureDevicePro.class.getName();
        }

        // 9.三相电表
        if (productKey.equals(IotProductEnum.THREE_AMMETER_DEVICE.getValue())) {
            result = ThreeAmmeterDevicePro.class.getName();
        }

        // 10.单向电表
        if (productKey.equals(IotProductEnum.ONE_AMMETER_DEVICE.getValue())) {
            result = OneAmmeterDevicePro.class.getName();
        }

        // 11.水表
        if (productKey.equals(IotProductEnum.WATER_METER_DEVICE.getValue())) {
            result = WaterMeterDevicePro.class.getName();
        }

        // 12.土壤酸碱度传感器
        if (productKey.equals(IotProductEnum.SOIL_PH_DEVICE.getValue())) {
            result = SoilPhDevicePro.class.getName();
        }

        // 13.土壤温湿度传感器
        if (productKey.equals(IotProductEnum.SOIL_HUMIDITY_DEVICE.getValue())) {
            result = SoilHumidityDevicePro.class.getName();
        }

        // 14.阀门控制器
        if (productKey.equals(IotProductEnum.VALVE_CONTROLLER_DEVICE.getValue())) {
            result = ValveControllerDevicePro.class.getName();
        }

        // 15.井盖监测器
        if (productKey.equals(IotProductEnum.MANHOLE_COVER_DEVICE.getValue())) {
            result = ManholeCoverDevicePro.class.getName();
        }

        // 16.风向传感器
        if (productKey.equals(IotProductEnum.WIND_DIRECTION_DEVICE.getValue())) {
            result = WindDirectionDevicePro.class.getName();
        }

        // 17.消防栓监测器
        if (productKey.equals(IotProductEnum.HYDRANT_DEVICE.getValue())) {
            result = HydrantDevicePro.class.getName();
        }

        // 18.风速传感器
        if (productKey.equals(IotProductEnum.WIND_SPEED_DEVICE.getValue())) {
            result = WindSpeedDevicePro.class.getName();
        }

        // 19.雨量传感器
        if (productKey.equals(IotProductEnum.RAINFALL_DEVICE.getValue())) {
            result = RainfallDevicePro.class.getName();
        }

        // 20.气象站
        if (productKey.equals(IotProductEnum.WEATHER_STATION_DEVICE.getValue())) {
            result = WeatherStationDevicePro.class.getName();
        }

        // 21.门磁传感器
        if (productKey.equals(IotProductEnum.DOOR_DEVICE.getValue())) {
            result = DoorDevicePro.class.getName();
        }

        // 22.LoRaWAN网关
        if (productKey.equals(IotProductEnum.LORAWAN_GATEWAY.getValue())) {
            result = LoRaWANDevicePro.class.getName();
        }
        return result;
    }



}








