package com.yuchen.saas.park.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.thinkunion.park.service.common.cache.CacheNames;
import com.yuchen.saas.park.api.entity.park.PmgBatIrrigateBind;
import com.yuchen.saas.park.api.enums.IotProductEnum;
import com.yuchen.saas.park.api.util.DeviceDataUtils;
import com.yuchen.saas.park.api.vo.park.devicepro.DeviceBasePro;
import com.yuchen.saas.park.api.vo.park.devicepro.SoilHumidityDevicePro;
import com.yuchen.saas.park.service.iot.IoTRemoteService;
import com.yuchen.saas.park.service.service.IrrigationService;
import com.yuchen.saas.park.service.service.PmgBatIrrigateBindService;
import org.nest.springwrap.core.redis.cache.NestRedis;
import org.springframework.stereotype.Service;

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

/**
 * @ClassName IrrigationServiceImpl
 * @Description 灌溉相关接口实现
 * @Author 张逸飞
 * @Date 2022/9/15 15:38
 */
@Service
public class IrrigationServiceImpl implements IrrigationService {

    /**
     * 灌溉相关设备-土壤温湿度传感器
     */
    private static String SOIL = IotProductEnum.SOIL_HUMIDITY_DEVICE.getValue();

    /**
     * 灌溉相关设备-阀门控制器
     */
    private static String VALVE = IotProductEnum.VALVE_CONTROLLER_DEVICE.getValue();

    /**
     * 注入设备数据工具类
     */
    @Resource
    private DeviceDataUtils deviceDataUtils;

    /**
     * 注入IOT调用操作接口
     */
    @Resource
    private IoTRemoteService ioTRemoteService;

    /**
     * redis 操作接口
     */
    @Resource
    private NestRedis nestRedis;

    /**
     * 注入灌溉设备绑定接口
     */
    @Resource
    private PmgBatIrrigateBindService irrigateBindService;

    @Override
    public Map<String, Object> getDeviceCount(Long parkId) {
        // 获取土壤温湿度传感器设备
        List<DeviceBasePro> soilList = deviceDataUtils.getDeviceDataFromCash(SOIL, parkId.toString());
        // 获取阀门控制器设备
        List<DeviceBasePro> valveList = deviceDataUtils.getDeviceDataFromCash(VALVE, parkId.toString());
        // 声明在离线数量
        Integer onLine = 0;
        Integer offLine = 0;
        // 声明要返回的Map
        for (DeviceBasePro deviceBasePro : soilList) {
            if (deviceBasePro.getIsOnline().equals(1)) {
                onLine++;
            } else {
                offLine++;
            }
        }
        // 声明要返回的阀门列表
        List<Map<String, Object>> valveMap = new ArrayList<>();
        for (DeviceBasePro deviceBasePro : valveList) {
            // 对象转Map
            Map<String, Object> map = BeanUtil.beanToMap(deviceBasePro);
            // 判断是否有绑定设备
            PmgBatIrrigateBind irrigateBind = irrigateBindService.getByDeviceName(deviceBasePro.getProductKey(),
                    deviceBasePro.getDeviceName());
            if (null != irrigateBind) {
                if(IotProductEnum.SOIL_HUMIDITY_DEVICE.getValue().equals(irrigateBind.getSoilProductKey())){
                    SoilHumidityDevicePro soiLDevice = (SoilHumidityDevicePro) deviceDataUtils.getDeviceInfoFromCash(parkId.toString(), irrigateBind.getSoilProductKey(), irrigateBind.getSoilDeviceName());
                    map.put("temperature", "");
                    map.put("humidity", "");
                    if (soiLDevice != null) {
                        if (soiLDevice.getTemperature() != null) {
                            map.put("temperature", soiLDevice.getTemperature());
                        }
                        if (soiLDevice.getHumidity() != null) {
                            map.put("humidity", soiLDevice.getHumidity());
                        }
                    }
                }
                map.put("sn", irrigateBind.getMonitor());
            } else {
                map.put("sn", "");
            }
            valveMap.add(map);
            if (deviceBasePro.getIsOnline().equals(1)) {
                onLine++;
            } else {
                offLine++;
            }
        }
        Map<String, Object> result = new HashMap<>(4);
        result.put("soilList", soilList);
        result.put("valveList", valveMap);
        result.put("onLine", onLine);
        result.put("offLine", offLine);
        return result;
    }

    @Override
    public Boolean irrigationControl(String productKey, String deviceName, Boolean status) {
        Map<String, Object> params = new HashMap<String, Object>(3);
        params.put("productKey", productKey);
        params.put("deviceName", deviceName);
        if (status) {
            params.put("identify", "open");
        } else {
            params.put("identify", "close");
        }
        Map<String, Object> body = new HashMap<>(1);
        body.put("open", status);
        params.put("params", body);
        return ioTRemoteService.callService(params);
    }

    @Override
    public void handleAutoIrrigation(String productKey, String deviceName, Float humidity) {
        // 判断是否有绑定设备
        PmgBatIrrigateBind irrigateBind = irrigateBindService.getByDeviceName(productKey, deviceName);
        if (null != irrigateBind) {
            Map<String, Float> map = getBoundaryValue(irrigateBind.getParkId());
            Float lowValue = map.get("lowValue");
            Float highValue = map.get("highValue");
            // 判断湿度是否达到界限
            if (humidity < lowValue) {
                // 湿度低了、打开阀门
                irrigationControl(irrigateBind.getImpulseProductKey(), irrigateBind.getImpulseDeviceName(), true);
            }
            if (humidity > highValue) {
                // 湿度高了、关闭阀门
                irrigationControl(irrigateBind.getImpulseProductKey(), irrigateBind.getImpulseDeviceName(), false);
            }
        }
    }

    @Override
    public Boolean setBoundaryValue(Long parkId, Float lowValue, Float highValue) {
        String lowValueKey = new StringBuilder(CacheNames.PARK_SOIL_HUMIDITY).append(parkId).append(":").append(
                "lowValue").toString();
        String highValueKey = new StringBuilder(CacheNames.PARK_SOIL_HUMIDITY).append(parkId).append(":").append(
                "highValue").toString();
        nestRedis.set(lowValueKey, lowValue);
        nestRedis.set(highValueKey, highValue);
        return true;
    }

    @Override
    public Map<String, Float> getBoundaryValue(Long parkId) {
        String lowValueKey = new StringBuilder(CacheNames.PARK_SOIL_HUMIDITY).append(parkId).append(":").append(
                "lowValue").toString();
        String highValueKey = new StringBuilder(CacheNames.PARK_SOIL_HUMIDITY).append(parkId).append(":").append(
                "highValue").toString();
        Map<String, Float> map = new HashMap<>(2);
        if (nestRedis.exists(lowValueKey)) {
            map.put("lowValue", nestRedis.get(lowValueKey));
            map.put("highValue", nestRedis.get(highValueKey));
        } else {
            map.put("lowValue", Float.valueOf(0));
            map.put("highValue", Float.valueOf(0));
        }
        return map;
    }
}
