package com.ruoyi.bst.device.utils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.ruoyi.bst.device.constants.DeviceCacheKey;
import com.ruoyi.bst.device.domain.Device;
import com.ruoyi.bst.device.domain.DeviceVO;
import com.ruoyi.bst.device.domain.enums.DeviceLocationType;
import com.ruoyi.bst.orderDevice.domain.enums.OrderDeviceStatus;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.common.utils.map.GpsCoordinateUtils;
import com.ruoyi.iot.domain.IotDeviceInfo;
import com.ruoyi.iot.domain.IotDeviceSysInfo;
import com.ruoyi.iot.service.impl.DeviceOnlineStatus;

public class DeviceUtil {

    public static void setIotSysInfo(DeviceVO device, IotDeviceSysInfo sys, LocalDateTime at, boolean setNull) {
        setIotSysInfo(device, sys, at, setNull, DeviceLocationType.DEVICE);
    }

    /**
     * 设置设备系统信息
     *
     * @param device          设备
     * @param sys             设备信息
     * @param at              时间
     * @param setNull         若定位不正常，是否设置为空
     * @param convertLocation 是否转换经纬度坐标系
     */
    public static void setIotSysInfo(DeviceVO device, IotDeviceSysInfo sys, LocalDateTime at, boolean setNull,
            DeviceLocationType locationType) {
        if (device == null || sys == null) {
            return;
        }

        // 转换经纬度坐标系并赋值
        // 只有定位是正常的 && 卫星信号不弱 才认为是有获取到定位
        if (DeviceUtil.validLocation(sys.getLon(), sys.getLat()) && !DeviceUtil.isLowSatelliteSignal(sys.getS())) {
            List<BigDecimal> coordinates = null;

            // 转换坐标
            if (locationType == DeviceLocationType.DEVICE) {
                coordinates = GpsCoordinateUtils.coordinateConvert(sys.getLon(), sys.getLat());
            } else if (locationType == DeviceLocationType.PHONE) {
                coordinates = Arrays.asList(sys.getLon(), sys.getLat());
            }

            if (coordinates != null && coordinates.size() >= 2) {
                device.setLongitude(coordinates.get(0));
                device.setLatitude(coordinates.get(1));
                device.setLastLocationTime(at);
                device.setLocationType(locationType.getCode());
            }
        } else if (setNull) {
            device.setLongitude(null);
            device.setLatitude(null);
            device.setLastLocationTime(null);
            device.setLocationType(null);
        }

        device.setLastTime(at);
        device.setVoltage(sys.getBat());
        device.setSignalStrength(sys.getCsq());
        device.setQuality(sys.getQ());
        device.setSatellites(sys.getS());
        device.setIotStatus(sys.getStatus());
    }

    /**
     * 设置设备信息
     *
     * @param device 设备
     * @param iot    设备信息
     */
    public static void setIotInfo(DeviceVO device, IotDeviceInfo iot) {
        if (device == null || iot == null) {
            return;
        }

        IotDeviceSysInfo sys = iot.getSys();
        if (sys != null) {
            setIotSysInfo(device, sys, iot.getAt(), false);
        }
        device.setSoftwareVersion(iot.getVer());
    }

    /**
     * 设置设备信息
     *
     * @param device 设备
     * @param info   设备信息
     */
    public static void setIotInfo(Device device, Map<String, Object> info) {
        if (device == null || info == null) {
            return;
        }
        
        // 设置设备信息
        if (info.containsKey(DeviceCacheKey.VOLTAGE)) {
            device.setVoltage(JsonUtils.getBigDecimal(info.get(DeviceCacheKey.VOLTAGE)));
        }
        if (info.containsKey(DeviceCacheKey.SIGNAL_STRENGTH)) {
            device.setSignalStrength(JsonUtils.getInteger(info.get(DeviceCacheKey.SIGNAL_STRENGTH)));
        }
        if (info.containsKey(DeviceCacheKey.QUALITY)) {
            device.setQuality(String.valueOf(info.get(DeviceCacheKey.QUALITY)));
        }
        if (info.containsKey(DeviceCacheKey.SATELLITES)) {
            device.setSatellites(JsonUtils.getInteger(info.get(DeviceCacheKey.SATELLITES)));
        }
        if (info.containsKey(DeviceCacheKey.IOT_STATUS)) {
            device.setIotStatus(String.valueOf(info.get(DeviceCacheKey.IOT_STATUS)));
        }
        if (info.containsKey(DeviceCacheKey.LONGITUDE)) {
            device.setLongitude(JsonUtils.getBigDecimal(info.get(DeviceCacheKey.LONGITUDE)));
        }
        if (info.containsKey(DeviceCacheKey.LATITUDE)) {
            device.setLatitude(JsonUtils.getBigDecimal(info.get(DeviceCacheKey.LATITUDE)));
        }
        if (info.containsKey(DeviceCacheKey.LAST_TIME)) {
            device.setLastTime(JsonUtils.getLocalDatetime(info.get(DeviceCacheKey.LAST_TIME)));
        }
        if (info.containsKey(DeviceCacheKey.LAST_LOCATION_TIME)) {
            device.setLastLocationTime(JsonUtils.getLocalDatetime(info.get(DeviceCacheKey.LAST_LOCATION_TIME)));
        }
        if (info.containsKey(DeviceCacheKey.SOFTWARE_VERSION)) {
            device.setSoftwareVersion(String.valueOf(info.get(DeviceCacheKey.SOFTWARE_VERSION)));
        }
        if (info.containsKey(DeviceCacheKey.LOCATION_TYPE)) {
            device.setLocationType(String.valueOf(info.get(DeviceCacheKey.LOCATION_TYPE)));
        }

        // 在线状态
        if (info.containsKey(DeviceCacheKey.ONLINE_STATUS)) {
            device.setOnlineStatus(String.valueOf(info.get(DeviceCacheKey.ONLINE_STATUS)));
        }
        if (info.containsKey(DeviceCacheKey.LAST_ONLINE_TIME)) {
            device.setLastOnlineTime(JsonUtils.getLocalDatetime(info.get(DeviceCacheKey.LAST_ONLINE_TIME)));
        }
    }

    /**
     * 判断设备是否有订单正在使用
     *
     * @param device 设备
     * @return 是否正在使用
     */
    public static boolean isOrderUsing(DeviceVO device) {
        return device != null && device.getOrderDeviceId() != null
                && OrderDeviceStatus.inUse().contains(device.getOrderDeviceStatus());
    }

    /**
     * 判断经纬度是否有效
     *
     * @param lon 经度
     * @param lat 纬度
     * @return 是否有效
     */
    public static boolean validLocation(BigDecimal lon, BigDecimal lat) {
        return lon != null && lat != null
                && !MathUtils.equals(lon, BigDecimal.ZERO)
                && !MathUtils.equals(lat, BigDecimal.ZERO);
    }

    /**
     * 判断设备信号是否弱
     *
     * @param device 设备
     * @return 是否弱
     */
    public static boolean isLowSignal(DeviceVO device) {
        return device != null && device.getSignalStrength() != null && device.getSignalStrength() < 10;
    }

    /**
     * 判断卫星信号是否弱
     *
     * @param device 设备
     * @return 是否弱
     */
    public static boolean isLowSatelliteSignal(DeviceVO device) {
        return device != null && isLowSatelliteSignal(device.getSatellites());
    }

    /**
     * 卫星信号弱
     * @param s
     * @return
     */
    public static boolean isLowSatelliteSignal(Integer s) {
        return s == null || s <= 5;
    }

    /**
     * 根据推送设置设备信息
     *
     * @param device 设备
     * @param sys    sys信息
     * @param at     时间
     * @param setNull 是否设置为空
     */
    public static void setIotSysInfoByReceive(DeviceVO device, IotDeviceSysInfo sys, LocalDateTime at, boolean setNull) {
        setIotSysInfo(device, sys, at, setNull);

        device.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus());
        device.setLastOnlineTime(at);
    }

    /**
     * 判断设备是否离线
     *
     * @param device 设备
     * @return 是否离线
     */
    public static boolean isOffline(DeviceVO device) {
        return device != null && device.getOnlineStatus() != null && DeviceOnlineStatus.OFFLINE.getStatus().equals(device.getOnlineStatus());
    }
}
