package com.mortals.xhx.module.device.service.impl;

import cn.hutool.core.net.url.UrlPath;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.ErrorLogPdu;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.system.message.MessageService;
import com.mortals.xhx.base.system.message.impl.MessageProducer;
import com.mortals.xhx.busiz.req.DeviceMsgReq;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.common.code.*;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.key.QueueKey;
import com.mortals.xhx.common.key.RedisKey;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import com.mortals.xhx.common.model.MessageHeader;
import com.mortals.xhx.common.pdu.DeviceReq;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.feign.IFillDeviceFeign;
import com.mortals.xhx.feign.IInfoPublishDeviceFeign;
import com.mortals.xhx.feign.IOfficeDeviceFeign;
import com.mortals.xhx.feign.ISampleDeviceFeign;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.device.dao.DeviceDao;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceLogEntity;
import com.mortals.xhx.module.device.model.DeviceMapEntity;
import com.mortals.xhx.module.device.model.DeviceQuery;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.platform.model.PlatformEntity;
import com.mortals.xhx.module.platform.model.PlatformQuery;
import com.mortals.xhx.module.platform.service.PlatformService;
import com.mortals.xhx.module.product.model.ProductEntity;
import com.mortals.xhx.module.product.model.ProductQuery;
import com.mortals.xhx.module.product.service.ProductService;
import com.mortals.xhx.module.site.model.SiteEntity;
import com.mortals.xhx.module.site.service.SiteService;
import com.mortals.xhx.queue.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

import static com.mortals.xhx.common.key.Constant.MESSAGETYPE_NOTIFY_RESTART_APP;
import static java.math.BigDecimal.ROUND_HALF_DOWN;

/**
 * DeviceService
 * 设备 service实现
 *
 * @author zxfei
 * @date 2022-03-09
 */
@Service("deviceService")
@Slf4j
public class DeviceServiceImpl extends AbstractCRUDCacheServiceImpl<DeviceDao, DeviceEntity, Long> implements DeviceService {

    @Autowired
    @Lazy
    private ProductService productService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private ISiteFeign siteFeign;
    @Autowired
    private DeviceLogService deviceLogService;
    @Autowired
    private MessageProducer messageProducer;
    @Autowired
    private DirectMessageListenerContainer container;
    @Autowired
    private MessageService messageService;
    @Autowired
    private IOfficeDeviceFeign officeDeviceFeign;
    @Autowired
    private ISampleDeviceFeign sampleDeviceFeign;
    @Autowired
    private IFillDeviceFeign fillDeviceFeign;

    @Autowired
    private IInfoPublishDeviceFeign infoPublishDeviceFeign;

    @Value("${thirdPartyPath:/inter/device/deviceIn}")
    private String thirdPartyPath;

    @Value("${platform.type:cloud}")
    private String platFormType;//版本，默认云服务版本
    @Autowired
    private SiteService siteService;

    public void refresh() {
        log.info("开始初始化系统参数...");
        try {
            super.removeAllCache();
            super.loadCache();
            log.info("系统参数初始化完成！");
        } catch (Exception e) {
            log.error("查询系统参数异常", e);
        }
    }

    @Override
    protected String getExtKey(DeviceEntity data) {
        return data.getDeviceCode();
    }

    @Override
    protected void validData(DeviceEntity entity, Context context) throws AppException {
        if (ObjectUtils.isEmpty(entity.newEntity())) {
            if (ObjectUtils.isEmpty(entity.getPlatformId())) {
                throw new AppException("所属平台不能为空！");
            }
            if (ObjectUtils.isEmpty(entity.getProductId())) {
                throw new AppException("所属产品不能为空！");
            }
        }
        super.validData(entity, context);
    }

    @Override
    public String importList(List<DeviceEntity> list, Boolean updateSupport, Context context) {
        if (ObjectUtils.isEmpty(list)) {
            throw new AppException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        //去掉list中设备编码已重复的
        for (DeviceEntity entity : list) {
            try {
                entity.setDeviceCode(StrUtil.replace(entity.getDeviceCode(), ":", "-"));
                DeviceEntity deviceEntity = this.getCache(entity.getDeviceCode());
                if (ObjectUtils.isEmpty(deviceEntity)) {
                    //新增
                    entity.setCreateUserId(context == null ? 1L : context.getUser() == null ? 1L : context.getUser().getId());
                    entity.setCreateTime(new Date());
                    DeviceEntity save = this.save(entity, context);
                    if (save != null) {
                        successNum++;
                    }
                } else {
                    //更新
                    entity.setId(deviceEntity.getId());
                    entity.setUpdateUserId(getContextUserId(context));
                    entity.setUpdateTime(new Date());
                    DeviceEntity update = this.update(entity, context);
                    if (update != null) {
                        successNum++;
                    }
                }
            } catch (Exception e) {
                log.error("导入异常", e);
                failureNum++;
            }
        }
        successMsg.append("导入成功！共 " + successNum + " 条");
        if (failureNum > 0) {
            successMsg.append("\n");
            failureMsg.append("导入失败！共 " + failureNum + " 条数据格式不正确");
            successMsg.append(failureMsg);
        }
        return successMsg.toString();
    }

    @Override
    public ApiResp<String> sendDeviceMessage(DeviceEntity deviceEntity, TopicPartitionInfo info, TbQueueMsgHeaders header, String message, TbQueueCallback callback, Context context) {
        ApiResp<String> resp = new ApiResp<>();
        resp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        resp.setMsg(ApiRespCodeEnum.SUCCESS.getLabel());

        messageService.send(info, header, message, callback);
        return resp;
    }

    @Override
    public ApiResp<String> sendDeviceMessage(List<Long> deviceIds, TopicPartitionInfo info, TbQueueMsgHeaders header, String message, Context context) {
        ApiResp<String> resp = new ApiResp<>();
        DeviceQuery deviceQuery = new DeviceQuery();
        deviceQuery.setIdList(deviceIds);
        List<DeviceEntity> deviceEntityList = this.find(deviceQuery);
        for (DeviceEntity deviceEntity : deviceEntityList) {
            resp = sendDeviceMessage(deviceEntity, info, header, message, null, context);
        }
        return resp;
    }

    @Override
    public void active(String deviceCode, Context context) {
        DeviceEntity deviceEntity = this.selectOne(new DeviceQuery().deviceCode(deviceCode));
        if (ObjectUtils.isEmpty(deviceEntity)) throw new AppException("当前设备不存在！");
        if (deviceEntity.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
            throw new AppException("当前设备已激活！");
        deviceEntity.setDeviceStatus(DeviceStatusEnum.离线.getValue());
        deviceEntity.setOfflineTime(new Date());
        deviceEntity.setEnabled(EnabledEnum.启用.getValue());
        this.update(deviceEntity);
        PlatformEntity platformEntity = platformService.getCache(deviceEntity.getPlatformId() == null ? "-1" : deviceEntity.getPlatformId().toString());
        ProductEntity productEntity = productService.getCache(deviceEntity.getProductId() == null ? "-1" : deviceEntity.getProductId().toString());
        if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
            //注册rabbmit相关队列与绑定
            messageProducer.queueAddAndBinds(QueueKey.DEFAULT_EXCHANGE, Constant.UPLOAD_TOPIC + deviceCode, Constant.UPLOAD_TOPIC + deviceCode);
            messageProducer.queueAddAndBinds(QueueKey.DEFAULT_EXCHANGE, Constant.DOWN_TOPIC + deviceCode, Constant.DOWN_TOPIC + deviceCode);
            //订阅上行队列
            // container.addQueueNames(Constant.UPLOAD_TOPIC + deviceCode);

                restartMessageListener(Constant.UPLOAD_TOPIC + deviceCode);


            //新增设备通知第三方平台,先新增后激活
            sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ADD);
            sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ACTIVE);
        }

    }

    @Override
    public void restartApp(DeviceEntity deviceEntity, Context context) {
        if (ObjectUtils.isEmpty(deviceEntity.getIdList())) {
            throw new AppException("请选择需要重启应用的设备！");
        }

        List<DeviceEntity> deviceEntities = this.find(deviceEntity, context);
        for (DeviceEntity device : deviceEntities) {
            if (!ObjectUtils.isEmpty(device)) {
                TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
                header.put(MessageHeader.MESSAGETYPE, MESSAGETYPE_NOTIFY_RESTART_APP);
                header.put(MessageHeader.DEVICECODE, device.getDeviceCode());
                header.put(MessageHeader.TIMESTAMP, DateUtils.getCurrStrDateTime());
                TbQueueMsg queueMsg = new DefaultTbQueueMsg(IdUtil.fastUUID(), "W10=", header);
                messageProducer.sendMsg(QueueKey.DEFAULT_EXCHANGE, Constant.DOWN_TOPIC + device.getDeviceCode(), JSON.toJSONString(queueMsg));

                DeviceLogEntity deviceLogEntity = new DeviceLogEntity();
                deviceLogEntity.initAttrValue();
                deviceLogEntity.setTraceID(IdUtil.fastSimpleUUID());
                deviceLogEntity.setSiteId(device.getSiteId());
                deviceLogEntity.setDeviceId(device.getId());
                deviceLogEntity.setDeviceName(device.getDeviceName());
                deviceLogEntity.setDeviceCode(device.getDeviceCode());
                deviceLogEntity.setMessageHead(MESSAGETYPE_NOTIFY_RESTART_APP);
                deviceLogEntity.setContent("W10=");
                deviceLogEntity.setLogType(LogTypeEnum.下发服务.getValue());
                deviceLogEntity.setCreateUserId(1L);
                deviceLogEntity.setCreateTime(new Date());
                deviceLogService.save(deviceLogEntity, null);
            } else {
                log.info("未找到设备，deviceCode:{}", device.getDeviceCode());
            }
        }


    }

    @Override
    public void batchUpdateHall(DeviceEntity deviceEntity, Context context) {
        if (ObjectUtils.isEmpty(deviceEntity.getIdList())) {
            throw new AppException("请选择需要更新大厅的设备！");
        }

        if (ObjectUtils.isEmpty(deviceEntity.getHallId())) {
            throw new AppException("设备所属大厅不能为空！");
        }

        DeviceQuery condition = new DeviceQuery();
        condition.setIdList(deviceEntity.getIdList());

        DeviceQuery deviceQuery = new DeviceQuery();
        deviceQuery.setHallId(deviceEntity.getHallId());
        deviceQuery.setHallName(deviceEntity.getHallName());
        deviceQuery.setUpdateTime(new Date());

        this.getDeviceDao().update(deviceQuery, condition);
    }

    @Override
    public void deviceEnabled(Long id, Integer enabled, Context context) {
        DeviceEntity deviceEntity = this.get(id, context);
        if (ObjectUtils.isEmpty(deviceEntity)) throw new AppException("当前设备不存在！");
        deviceEntity.setEnabled(enabled);
        deviceEntity.setUpdateTime(new Date());
        deviceEntity.setUpdateUserId(getContextUserId(context));
        this.getDeviceDao().update(deviceEntity);
        this.putCache(deviceEntity.getId().toString(), deviceEntity);
        PlatformEntity platformEntity = platformService.getCache(deviceEntity.getPlatformId() == null ? "-1" : deviceEntity.getPlatformId().toString());
        ProductEntity productEntity = productService.getCache(deviceEntity.getProductId() == null ? "-1" : deviceEntity.getProductId().toString());
        if (enabled == YesNoEnum.YES.getValue()) {
            this.sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ENABLED);
        } else {
            this.sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.STOP);
        }

        if (enabled == EnabledEnum.停止.getValue()) {
            ErrorLogPdu errorLogPdu = new ErrorLogPdu();
            errorLogPdu.initAttrValue();
            errorLogPdu.setTraceID(IdUtil.objectId());
            errorLogPdu.setAppName(productEntity.getProductCode());
            errorLogPdu.setMessage(deviceEntity.getDeviceName() + "设备停用!");
            errorLogPdu.setPlatform("webos");
            errorLogPdu.setCulprit("");
            errorLogPdu.setTags("");
            errorLogPdu.setLevel("INFO");
            errorLogPdu.setEnvironment("");
            errorLogPdu.setReleaseVersion("");
            errorLogPdu.setFingerprint(LogTypeEnum.上报事件.name());
            errorLogPdu.setThreadNo(Thread.currentThread().toString());
            errorLogPdu.setErrorStack(Thread.currentThread() + deviceEntity.getDeviceName() + "设备停用!");
            errorLogPdu.setContext("");
            errorLogPdu.setExtra("");
            errorLogPdu.setLogTime(new Date());
            messageProducer.syncErrorSend(errorLogPdu);
        }

    }

    @Override
    public void stopOrStartComsumeQueue(Long id, Integer status, Context context) {

        DeviceEntity deviceEntity = this.get(id, context);
        if (ObjectUtils.isEmpty(deviceEntity)) throw new AppException("当前设备不存在！");
        PlatformEntity platformEntity = platformService.getCache(deviceEntity.getPlatformId() == null ? "-1" : deviceEntity.getPlatformId().toString());
        ProductEntity productEntity = productService.getCache(deviceEntity.getProductId() == null ? "-1" : deviceEntity.getProductId().toString());
        String exchangeName = platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode();
        TopicPartitionInfo topicPartitionInfo = new TopicPartitionInfo(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode(), null, exchangeName);

        Set<TopicPartitionInfo> set = new HashSet<>();
        set.add(topicPartitionInfo);

    }


    @Override
    protected void saveAfter(DeviceEntity entity, Context context) throws AppException {
        super.saveAfter(entity, context);
        PlatformEntity platformEntity = platformService.getCache(entity.getPlatformId() == null ? "-1" : entity.getPlatformId().toString());
        ProductEntity productEntity = productService.getCache(entity.getProductId() == null ? "0" : entity.getProductId().toString());
        if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
            //注册rabbmit相关队列与绑定 激活后才註冊綁定隊列
            // registerRabbitQueue(entity, platformEntity, productEntity);
        } else {
            throw new AppException("产品或平台不存在！");
        }
    }

    @Override
    protected void updateAfter(DeviceEntity entity, Context context) throws AppException {
        super.updateAfter(entity, context);
        PlatformEntity platformEntity = platformService.getCache(entity.getPlatformId() == null ? "-1" : entity.getPlatformId().toString());
        ProductEntity productEntity = productService.getCache(entity.getProductId() == null ? "0" : entity.getProductId().toString());
        if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
            //新增设备通知第三方平台 激活后的设备才通知和更新
            if (entity.getDeviceStatus() > 0) {
                //注册rabbmit相关队列与绑定
                messageProducer.queueAddAndBinds(QueueKey.DEFAULT_EXCHANGE, Constant.UPLOAD_TOPIC + entity.getDeviceCode(), Constant.UPLOAD_TOPIC + entity.getDeviceCode());
                messageProducer.queueAddAndBinds(QueueKey.DEFAULT_EXCHANGE, Constant.DOWN_TOPIC + entity.getDeviceCode(), Constant.DOWN_TOPIC + entity.getDeviceCode());

                    restartMessageListener(Constant.UPLOAD_TOPIC + entity.getDeviceCode());

                //监听上行队列
                sendThirdParty(entity, productEntity, platformEntity, DeviceMethodEnum.UPDATE);
            }
        }
    }

    @Override
    public Rest<String> sendThirdParty(DeviceEntity entity, ProductEntity productEntity, PlatformEntity platformEntity, DeviceMethodEnum update) {
        //todo 修改为异步发送消息，当前消息存放到redis的队列中
        DeviceReq deviceReq = new DeviceReq();
        BeanUtils.copyProperties(entity, deviceReq, BeanUtil.getNullPropertyNames(entity));
        deviceReq.setDeviceStatus(update.getValue());
        deviceReq.setProductCode(productEntity.getProductCode());
        deviceReq.setDeviceInBuilding(entity.getDeviceInBuilding() == null ? 0 : entity.getDeviceInBuilding());
        deviceReq.setDeviceInFloor(entity.getDeviceInFloor() == null ? 0 : entity.getDeviceInFloor());
        //http://192.168.0.98:8090/inter/device/deviceIn
        //判断是否是php，如果不是 则是java 则内部调用
        try {
            if ("smartOffice".equals(platformEntity.getPlatformSn())) {
                deviceReq.setReceiveMethod(update.getValue());
                //todo 调用智慧办公系统
                Rest<String> officeRest = officeDeviceFeign.deviceCall(deviceReq);
                log.info("office  resp ==>{}", JSON.toJSONString(officeRest));
            }
            if ("ybxt".equals(platformEntity.getPlatformSn())) {
                deviceReq.setReceiveMethod(update.getValue());
                //调用样表系统系统
                Rest<String> sampleRest = sampleDeviceFeign.deviceCall(deviceReq);
                log.info("sample  resp ==>{}", JSON.toJSONString(sampleRest));
            }

            if ("xxgk".equals(platformEntity.getPlatformSn())) {
                deviceReq.setReceiveMethod(update.getValue());
                //调用样表系统系统
                Rest<String> sampleRest = infoPublishDeviceFeign.deviceCall(deviceReq);
                log.info("info publish  resp ==>{}", JSON.toJSONString(sampleRest));
            }

            if ("tdxt".equals(platformEntity.getPlatformSn())) {
                deviceReq.setReceiveMethod(update.getValue());
                //调用样表系统系统
                Rest<String> fillRest = fillDeviceFeign.deviceCall(deviceReq);
                log.info("fill  resp ==>{}", JSON.toJSONString(fillRest));
            } else {
                cacheService.lpush(RedisKey.KEY_DEVICE_THIRDPARTY_QUEUE, deviceReq);
            }
        } catch (Exception e) {
            log.error("feign调用异常！");
        }

        return Rest.ok();
    }

    @Override
    public void putCache(String key, DeviceEntity data) {
        super.putCache(key, data);
    }


    @Override
    public DeviceDao getDeviceDao() {
        return this.getDao();
    }


    @Override
    public List<DeviceMapEntity> deviceMap(DeviceEntity query, Context context) {
        String longitude = "0.00";
        String latitude = "0.00";
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
            SiteEntity siteEntity = siteService.get(query.getSiteId());
            if (ObjectUtils.isEmpty(siteEntity)) throw new AppException("未找到指定站点！");
            longitude = siteEntity.getLongitude();
            latitude = siteEntity.getLatitude();
        } else {
            Rest<SitePdu> info = siteFeign.info(query.getSiteId());
            if (info.getCode() != YesNoEnum.YES.getValue()) throw new AppException("获取站点信息失败！");
            SitePdu sitePdu = info.getData();
            longitude = sitePdu.getLongitude();
            latitude = sitePdu.getLatitude();
        }

        List<DeviceMapEntity> collect = this.find(query, context)
                .stream().collect(Collectors.groupingBy(x -> x.getProductId()))
                .entrySet()
                .stream().map(item -> {
                    DeviceMapEntity deviceMapEntity = new DeviceMapEntity();
                    deviceMapEntity.setProductId(item.getKey());
                    ProductEntity productEntity = productService.getCache(item.getKey() == null ? "-1" : item.getKey().toString());
                    deviceMapEntity.setProductCode(productEntity == null ? "" : productEntity.getProductCode());
                    if (ObjectUtils.isEmpty(item.getValue())) {
                        deviceMapEntity.setDeviceList(Collections.EMPTY_LIST);
                    } else {
                        deviceMapEntity.setDeviceList(item.getValue());
                    }
                    return deviceMapEntity;
                }).collect(Collectors.toList());
        //更新坐标点 轴步进 0.0001~~11米
        BigDecimal lngStep = new BigDecimal(0.00001);
        BigDecimal latiStep = new BigDecimal(0.00001);


        BigDecimal centerLng = new BigDecimal(longitude);
        BigDecimal centerlati = new BigDecimal(latitude);

        for (int i = 1; i <= collect.size(); i++) {
            BigDecimal curLati = new BigDecimal(latitude);
            if (i % 2 == 1) {
                curLati = centerlati.subtract(latiStep.multiply(new BigDecimal(i)));
            } else {
                curLati = centerlati.add(latiStep.multiply(new BigDecimal(i)));
            }

            for (int j = 1; j <= collect.get(i - 1).getDeviceList().size(); j++) {
                //偶数加，奇数减
                BigDecimal curLng = new BigDecimal(longitude);
                if (j % 2 == 1) {
                    curLng = centerLng.subtract(lngStep.multiply(new BigDecimal(j)));
                } else {
                    curLng = centerLng.add(lngStep.multiply(new BigDecimal(j)));
                }
                DeviceEntity deviceEntity = collect.get(i - 1).getDeviceList().get(j - 1);
                deviceEntity.setLon(curLng.setScale(6, RoundingMode.HALF_UP).toString());
                deviceEntity.setLati(curLati.setScale(6, RoundingMode.HALF_UP).toString());
            }
        }
        return collect;

    }


    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        Long[] removeIds = Arrays.asList(ids).stream().map(id -> {
            DeviceEntity deviceEntity = this.get(id, context);
            if (!ObjectUtils.isEmpty(deviceEntity)) {
                PlatformEntity platformEntity = platformService.getCache(deviceEntity.getPlatformId().toString());
                ProductEntity productEntity = productService.getCache(deviceEntity.getProductId().toString());
                if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
                    Rest<String> thirtyRest = sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.DEL);
                    if (YesNoEnum.YES.getValue() == thirtyRest.getCode()) {

                        TbQueueCallback callback = new TbQueueCallback() {
                            @Override
                            public void onSuccess(TbQueueMsgMetadata metadata) {
                                log.info("队列删除成功");
                            }

                            @Override
                            public void onFailure(Throwable t) {
                                log.error("队列删除失败", t);

                            }
                        };
                        messageProducer.queueDelete(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode());
                        messageProducer.queueDelete(Constant.DOWN_TOPIC + deviceEntity.getDeviceCode());
                        //删除监听器
                        container.removeQueueNames(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode());
                        container.removeQueueNames(Constant.DOWN_TOPIC + deviceEntity.getDeviceCode());
                        //删除扩展extKey
                        this.removeCache(deviceEntity.getDeviceCode());
                        return id;
                    }
                }
            }
            return null;
        }).toArray(Long[]::new);
        super.removeBefore(removeIds, context);
    }

    @Override
    protected void exportAfter(DeviceEntity params, Context context, List<DeviceEntity> list) throws AppException {
        list.stream().forEach(deviceEntity -> {
            PlatformEntity platformEntity = platformService.getCache(deviceEntity.getPlatformId().toString());
            ProductEntity productEntity = productService.getCache(deviceEntity.getProductId().toString());
            if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
                deviceEntity.setProductCode(productEntity.getProductCode());
                deviceEntity.setPlatformCode(platformEntity.getPlatformSn());
            }
        });
        super.exportAfter(params, context, list);
    }

    @Override
    protected void saveBefore(DeviceEntity entity, Context context) throws AppException {
        super.saveBefore(entity, context);
        if (ObjectUtils.isEmpty(entity.getDeviceCode())) {
            throw new AppException("设备编码不能为空！");
        }
        entity.setDeviceCode(StrUtil.replace(entity.getDeviceCode(), ":", "-"));
        if (ObjectUtils.isEmpty(entity.getDeviceMac())) {
            entity.setDeviceMac(entity.getDeviceCode());
        } else {
            entity.setDeviceMac(StrUtil.replace(entity.getDeviceMac(), ":", "-"));
        }

        //设备编码唯一
        DeviceEntity deviceEntity = this.selectOne(new DeviceQuery().deviceCode(entity.getDeviceCode()));
        if (!ObjectUtils.isEmpty(deviceEntity)) {
            //如果原始的域当前的站点不一致，做更新处理，否则提示编码重复
            if (!ObjectUtils.isEmpty(entity.getSiteId()) && entity.getSiteId() != deviceEntity.getSiteId()) {
                entity.setId(deviceEntity.getId());
                entity.setUpdateTime(new Date());
                entity.setUpdateUserId(getContextUserId(context));
            } else {
                throw new AppException("设备编码重复！");
            }
        }

        if (!ObjectUtils.isEmpty(entity.getProductId())) {
            ProductEntity productEntity = productService.get(entity.getProductId());
            if (!ObjectUtils.isEmpty(productEntity)) {
                entity.setProductId(productEntity.getId());
                entity.setProductCode(productEntity.getProductCode());
                entity.setProductName(productEntity.getProductName());
                //根据产品查询平台
                if (!ObjectUtils.isEmpty(productEntity.getPlatformId())) {
                    PlatformEntity platformEntity = platformService.getCache(productEntity.getPlatformId().toString());
                    entity.setPlatformId(platformEntity.getId());
                    entity.setPlatformCode(platformEntity.getPlatformSn());
                    entity.setPlatformName(platformEntity.getPlatformName());
                }
            }
        }

        if (!ObjectUtils.isEmpty(entity.getProductCode())) {
            ProductEntity productEntity = productService.selectOne(new ProductQuery().productCode(entity.getProductCode()));
            if (!ObjectUtils.isEmpty(productEntity)) {
                entity.setProductId(productEntity.getId());
                entity.setProductName(productEntity.getProductName());
                //根据产品查询平台
                if (!ObjectUtils.isEmpty(productEntity.getPlatformId())) {
                    PlatformEntity platformEntity = platformService.getCache(productEntity.getPlatformId().toString());
                    entity.setPlatformId(platformEntity.getId());
                    entity.setPlatformCode(platformEntity.getPlatformSn());
                    entity.setPlatformName(platformEntity.getPlatformName());
                }
            }
        } else if (!ObjectUtils.isEmpty(entity.getProductName())) {
            ProductEntity productEntity = productService.selectOne(new ProductQuery().productName(entity.getProductName()));
            if (!ObjectUtils.isEmpty(productEntity)) {
                entity.setProductId(productEntity.getId());
                entity.setProductCode(productEntity.getProductCode());
                //根据产品查询平台
                if (!ObjectUtils.isEmpty(productEntity.getPlatformId())) {
                    PlatformEntity platformEntity = platformService.getCache(productEntity.getPlatformId().toString());
                    entity.setPlatformId(platformEntity.getId());
                    entity.setPlatformCode(platformEntity.getPlatformSn());
                    entity.setPlatformName(platformEntity.getPlatformName());
                }
            }
        }
        if (!ObjectUtils.isEmpty(entity.getPlatformCode())) {
            PlatformEntity platformEntity = platformService.selectOne(new PlatformQuery().platformSn(entity.getPlatformCode()));
            if (!ObjectUtils.isEmpty(platformEntity)) {
                entity.setPlatformId(platformEntity.getId());
                entity.setPlatformName(platformEntity.getPlatformName());
            }
        }
        //如果负责人与电话为空，查询站点关联
        if (ObjectUtils.isEmpty(entity.getLeadingOfficial()) || ObjectUtils.isEmpty(entity.getSiteCode())) {
            updateDeviceEntityBySite(entity);
        }

        if (!ObjectUtils.isEmpty(entity.getDeviceStatus()) && entity.getDeviceStatus() > DeviceStatusEnum.未激活.getValue()) {
            //激活设备，添加队列订阅
            //container.addQueueNames(Constant.UPLOAD_TOPIC + entity.getDeviceCode());

                restartMessageListener(Constant.UPLOAD_TOPIC + entity.getDeviceCode());
        
            PlatformEntity platformEntity = platformService.getCache(entity.getPlatformId().toString());
            ProductEntity productEntity = productService.getCache(entity.getProductId().toString());
            sendThirdParty(entity, productEntity, platformEntity, DeviceMethodEnum.ADD);
            sendThirdParty(entity, productEntity, platformEntity, DeviceMethodEnum.ACTIVE);
        }
        updateDeviceHomeUrl(entity);

    }

    @Override
    protected void updateBefore(DeviceEntity entity, Context context) throws AppException {
        super.updateBefore(entity, context);
        ProductEntity productEntity = productService.get(entity.getProductId(), context);
        entity.setProductCode(productEntity == null ? "" : productEntity.getProductCode());
        updateDeviceHomeUrl(entity);
    }

    private void updateDeviceHomeUrl(DeviceEntity entity) {
        if (!ObjectUtils.isEmpty(entity.getSkinName())) {
            String path = UrlPath.of(Constant.DEVICE_BASEHOME_PATH, Charset.defaultCharset())
                    .add(entity.getProductCode())
                    .add(entity.getSkinName())
                    .toString();
            entity.setHomeUrl(path);
        }
        //判断当前站点与修改的站点不一致时候 更新设备站点关联信息
        if (!ObjectUtils.isEmpty(entity.getId())) {
            DeviceEntity temp = this.get(entity.getId(), null);
            if (!ObjectUtils.isEmpty(entity.getSiteId())) {
                if (!entity.getSiteId().equals(temp.getSiteId())) {
                    updateDeviceEntityBySite(entity);
                } else {
                    if (ObjectUtils.isEmpty(entity.getSiteCode()) || ObjectUtils.isEmpty(entity.getSiteName())) {
                        updateDeviceEntityBySite(entity);
                    }
                }
            }
        }
    }

    private void updateDeviceEntityBySite(DeviceEntity entity) {
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
            SiteEntity siteEntity = siteService.get(entity.getSiteId());
            if (!ObjectUtils.isEmpty(siteEntity)) {
                entity.setLeadingOfficial(siteEntity.getLeadingOfficial());
                entity.setLeadingOfficialTelephone(siteEntity.getLeadingOfficialTelephone());
                entity.setSiteCode(siteEntity.getSiteCode());
                entity.setSiteName(siteEntity.getSiteName());
            }
        } else {
            Rest<SitePdu> info = siteFeign.info(entity.getSiteId());
            if (info.getCode() == YesNoEnum.YES.getValue()) {
                entity.setLeadingOfficial(info.getData().getLeadingOfficial());
                entity.setLeadingOfficialTelephone(info.getData().getLeadingOfficialTelephone());
                entity.setSiteCode(info.getData().getSiteCode());
                entity.setSiteName(info.getData().getSiteName());
            }
        }
    }

    @Override
    public void downMsg(List<DeviceMsgReq> list) {
        try {
            // ArrayList<DeviceLogEntity> deviceLogList = new ArrayList<>();
            List<DeviceMsgReq> collect = list.stream().sorted(Comparator.comparing(DeviceMsgReq::getTimestamp)).collect(Collectors.toList());

            for (DeviceMsgReq item : collect) {
                //根据设备编码查询设备
                DeviceEntity deviceEntity = null;
                try {
                    deviceEntity = this.getExtCache(item.getDeviceCode());
                } catch (Exception e) {
                    log.info("deviceCode:{}", item.getDeviceCode());
                    log.error("redis 获取设备异常！", e);
                    continue;
                }
                if (!ObjectUtils.isEmpty(deviceEntity)) {
                    TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
                    header.put(MessageHeader.MESSAGETYPE, item.getMessageType());
                    header.put(MessageHeader.DEVICECODE, item.getDeviceCode());
                    header.put(MessageHeader.TIMESTAMP, item.getTimestamp().toString());

                    TbQueueMsg queueMsg = new DefaultTbQueueMsg(IdUtil.fastUUID(), item.getData(), header);

                    CorrelationData correlationData = new CorrelationData();
                    correlationData.setId(deviceEntity.getDeviceCode());
                    log.info("send rabbitmq msg:{}", item.getDeviceCode());
                    messageProducer.sendMsg(QueueKey.DEFAULT_EXCHANGE, Constant.DOWN_TOPIC + deviceEntity.getDeviceCode(), JSON.toJSONString(queueMsg), correlationData);
                } else {
                    log.info("未找到设备，deviceCode:{}", item.getDeviceCode());
                }
            }

        } catch (Exception e) {
            log.error("异常：", e);
        }
    }


    /**
     * 重启对消息队列的监听
     *
     * @param queueName
     * @return
     */
    public boolean restartMessageListener(String queueName) {
        try {
            String key = StringUtils.trim(queueName);
            container.addQueueNames(key);

            if (container.isRunning()) {
                container.stop();
                container.start();
            }
            container.start();
        } catch (AppException e) {
            log.error("重启消息监听失败", e);
            return false;
        }
        return true;
    }


    public static void main(String[] args) {
        BigDecimal bigDecimal = new BigDecimal("104.22241");
        BigDecimal add = bigDecimal.add(new BigDecimal("0.01"));


        System.out.println(add.toString());

        int deviceOnlineCount = 157;

        int deviceActiveCount = 637;

        BigDecimal bigDecimalend = new BigDecimal(deviceOnlineCount);
        BigDecimal bigDecimal2 = new BigDecimal(deviceActiveCount);


        BigDecimal bigDecimal1 = bigDecimalend.divide(bigDecimal2, 2, ROUND_HALF_DOWN);

        System.out.println(bigDecimal1.toString());


        BigDecimal divide = new BigDecimal(deviceOnlineCount).divide(new BigDecimal(deviceActiveCount), 4, ROUND_HALF_DOWN);


        System.out.println(divide.toString());

    }


}