package com.fastbee.data.service.impl;

import com.fastbee.common.constant.FastBeeConstant;
import com.fastbee.common.core.mq.ota.OtaUpgradeBo;
import com.fastbee.common.core.mq.ota.OtaUpgradeDelayTask;
import com.fastbee.common.exception.ServiceException;
import com.fastbee.data.service.IOtaUpgradeService;
import com.fastbee.iot.domain.Device;
import com.fastbee.iot.domain.Firmware;
import com.fastbee.iot.service.IDeviceService;
import com.fastbee.iot.service.IFirmwareService;
import com.fastbee.iot.service.IProductService;
import com.fastbee.mq.service.IMessagePublishService;
import com.fastbee.mqtt.manager.MqttRemoteManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * OTA延迟升级实现
 *
 * @author bill
 */
@Service
@Slf4j
public class OtaUpgradeServiceImpl implements IOtaUpgradeService {

    @Autowired
    private IFirmwareService firmwareService;
    @Autowired
    private IDeviceService deviceService;
    @Resource
    private IMessagePublishService messagePublishService;


    @Override
    public void upgrade(OtaUpgradeDelayTask task) {
        //查询固件版本信息
        Firmware firmware = firmwareService.selectFirmwareByFirmwareId(task.getFirmwareId());
        Optional.ofNullable(firmware).orElseThrow(() -> new ServiceException("固件版本不存在!"));
        // 处理单个或多个设备的OTA升级，根据设备单个升级
        if (!CollectionUtils.isEmpty(task.getDevices())) {
            for (String serialNumber : task.getDevices()) {
                Device device = deviceService.selectDeviceBySerialNumber(serialNumber);
                handleSingle(task, firmware, serialNumber, device.getDeviceName());
            }
            return;
        }
        // 根据产品查询设备整个产品升级处理
        handleProduct(task, firmware);
    }

    /**
     * 处理单个设备升级
     *
     * @param task         升级bo
     * @param firmware     固件
     * @param serialNumber 设备编号
     */
    private void handleSingle(OtaUpgradeDelayTask task, Firmware firmware, String serialNumber,String deviceName) {
        OtaUpgradeBo upgradeBo = OtaUpgradeBo.builder()
                .serialNumber(serialNumber)
                .taskId(task.getTaskId())
                .firmwareVersion(firmware.getVersion().toString())
                .otaId(firmware.getFirmwareId())
                .productId(firmware.getProductId())
                .otaUrl(firmware.getFilePath()) //文件升级URL
                .pushType(0) // 目前支持url升级，0表示url升级
                .seqNo(firmware.getSeqNo())
                .deviceName(deviceName)
                .firmwareName(firmware.getFirmwareName())
                .build();
        /* 校验设备是否在集群节点上*/
        if (MqttRemoteManager.checkDeviceStatus(serialNumber)) {
            //    客户端在本节点上，发布OTA升级,推送至MQ
            messagePublishService.publish(upgradeBo, FastBeeConstant.CHANNEL.UPGRADE);
        }
    }

    /**
     * 处理整个产品的设备升级
     *
     * @param task     升级bo
     * @param firmware 固件
     */
    private void handleProduct(OtaUpgradeDelayTask task, Firmware firmware) {
        //查询产品下的所有设备编码
        List<Device> deviceList = deviceService.selectDevicesByProductId(firmware.getProductId(),1);
        for (Device device : deviceList) {
            handleSingle(task, firmware, device.getSerialNumber(), device.getDeviceName());
        }
    }
}
