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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.net.url.UrlPath;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.ICacheService;
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.busiz.req.DeviceReq;
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.pdu.RespData;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.alarm.model.AlarmSmsSendEntity;
import com.mortals.xhx.module.alarm.model.AlarmSmsSendQuery;
import com.mortals.xhx.module.alarm.service.AlarmSmsSendService;
import com.mortals.xhx.module.device.dao.DeviceDao;
import com.mortals.xhx.module.device.model.*;
import com.mortals.xhx.module.device.service.DeviceAlarmInfoService;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.device.service.DeviceStatService;
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.queue.*;
import com.sun.javafx.fxml.builder.URLBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 java.math.BigDecimal.ROUND_HALF_DOWN;
import static java.util.stream.Collectors.counting;

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

    @Autowired
    private ProductService productService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private DefaultTbCoreConsumerService consumerService;
    @Autowired
    private ISiteFeign siteFeign;
    @Autowired
    private DeviceLogService deviceLogService;
    @Autowired
    private DeviceStatService deviceStatService;
    @Autowired
    private DeviceAlarmInfoService deviceAlarmInfoService;
    @Autowired
    private AlarmSmsSendService alarmSmsSendService;

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

    @Autowired
    private MessageService messageService;
    @Autowired
    private ICacheService cacheService;
    @Value("${thirdPartyPath:/inter/device/deviceIn}")
    private String thirdPartyPath;


    @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.setEnabled(EnabledEnum.启用.getValue());
        this.update(deviceEntity);
        PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
        ProductEntity productEntity = productService.get(deviceEntity.getProductId());
        if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
            //注册rabbmit相关队列与绑定
            registerRabbitQueue(deviceEntity, platformEntity, productEntity);

            TbQueueConsumer<TbQueueMsg> mainConsumer = consumerService.getMainConsumer();
            String exchangeName = platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode();
            TopicPartitionInfo topicPartitionInfo = new TopicPartitionInfo(Constant.UPLOAD_TOPIC + deviceCode, null, exchangeName);
            Set<TopicPartitionInfo> topicPartitionInfos = new HashSet<>();
            topicPartitionInfos.add(topicPartitionInfo);
            mainConsumer.subscribe(topicPartitionInfos);
            //新增设备通知第三方平台,先新增后激活
            sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ADD);
            sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ACTIVE);
        }

    }

    @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);
        ProductEntity productEntity = productService.get(deviceEntity.getProductId());
        PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
        if (enabled == YesNoEnum.YES.getValue()) {
            this.sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.ENABLED);
        } else {
            this.sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.STOP);
        }
    }

    @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.get(deviceEntity.getPlatformId());
        ProductEntity productEntity = productService.get(deviceEntity.getProductId());
        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);
        if (status == YesNoEnum.YES.getValue()) {
            //开启
            consumerService.getMainConsumer().subscribe(set);
        } else {
            //关闭
            consumerService.getMainConsumer().unsubscribe(set);
        }
    }


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

    private void registerRabbitQueue(DeviceEntity entity, PlatformEntity platformEntity, ProductEntity productEntity) {
        String exchangeName = platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode();
        TopicPartitionInfo info = TopicPartitionInfo.builder().exchangeName(exchangeName).topic(Constant.UPLOAD_TOPIC + entity.getDeviceCode()).build();
        TbQueueCallback callback = new TbQueueCallback() {
            @Override
            public void onSuccess(TbQueueMsgMetadata metadata) {
                log.debug("队列创建成功,设备编码:{}", entity.getDeviceCode());
            }

            @Override
            public void onFailure(Throwable t) {
                log.error("队列创建失败,设备通道编码:{},{}", entity.getDeviceCode(), t);

            }
        };
        messageService.queueDeclare(info, callback);
        //消费监听线程添加当前声明队列
        Set<TopicPartitionInfo> partitions = new HashSet<>();
        partitions.add(info);
        consumerService.getMainConsumer().subscribe(partitions);

        //创建下行队列
        info = TopicPartitionInfo.builder().exchangeName(exchangeName).topic(Constant.DOWN_TOPIC + entity.getDeviceCode()).build();
        messageService.queueDeclare(info, callback);
    }


    @Override
    protected void updateAfter(DeviceEntity entity, Context context) throws AppException {
        PlatformEntity platformEntity = platformService.get(entity.getPlatformId());
        ProductEntity productEntity = productService.get(entity.getProductId());
        if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {

            //新增设备通知第三方平台 激活后的设备才通知和更新
            if (entity.getDeviceStatus() > 0) {
                //注册rabbmit相关队列与绑定
                registerRabbitQueue(entity, platformEntity, productEntity);
                sendThirdParty(entity, productEntity, platformEntity, DeviceMethodEnum.UPDATE);
            }
        }
        super.updateAfter(entity, context);
    }

    @Override
    public void sendThirdParty(DeviceEntity entity, ProductEntity productEntity, PlatformEntity platformEntity, DeviceMethodEnum update) {
        DeviceReq deviceReq = new DeviceReq();
        BeanUtils.copyProperties(entity, deviceReq, BeanUtil.getNullPropertyNames(entity));
        deviceReq.setDeviceStatus(update.getValue());
        deviceReq.setProductCode(productEntity.getProductCode());
        if (!ObjectUtils.isEmpty(platformEntity.getSendUrl())
                //&& platformEntity.getSendSwitch() == SendSwitchEnum.启用.getValue()
                && entity.getSwitchSend()) {
            //http://192.168.0.98:8090/inter/device/deviceIn
            if (PatternPool.URL_HTTP.matcher(platformEntity.getSendUrl()).find()) {
                ApiResp<String> resp = messageService.sendThirdParty(UrlBuilder.of(platformEntity.getSendUrl()).addPath(thirdPartyPath).build(), deviceReq);
                log.info("sendThirtyis resp ==>{}", JSON.toJSONString(resp));
            } else {
                throw new AppException("http send url 不合法！" + platformEntity.getSendUrl());
            }
        } else {
            log.info("sendThirtyis null ==>{}", JSON.toJSONString(platformEntity));
        }
    }

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


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

    /**
     * 全部设备-》激活设备与未激活-》启用与停用设备-》离线与在线设备
     *
     * @param context
     */
    @Override
    public void deviceStat(Long siteId, Context context) {
        //查询当天统计，如果有 则更新统计结果，否则新增
        DeviceStatEntity deviceStatEntity = deviceStatService.selectOne(new DeviceStatQuery()
                .siteId(siteId)
                .year(DateUtil.year(new Date()))
                .month(DateUtil.month(new Date()) + 1)
                .day(DateUtil.dayOfMonth(new Date())));
        if (ObjectUtils.isEmpty(deviceStatEntity)) {
            deviceStatEntity = new DeviceStatEntity();
            deviceStatEntity.initAttrValue();
            deviceStatEntity.setSiteId(siteId);
            deviceStatEntity.setCreateTime(new Date());
            deviceStatEntity.setYear(DateUtil.year(new Date()));
            deviceStatEntity.setMonth(DateUtil.month(new Date()) + 1);
            deviceStatEntity.setDay(DateUtil.dayOfMonth(new Date()));
        }

        //获取昨天统计数据
        DeviceStatEntity yesterdayDeviceStat = deviceStatService.selectOne(new DeviceStatQuery()
                .siteId(siteId)
                .year(DateUtil.year(DateUtil.yesterday()))
                .month(DateUtil.month(DateUtil.yesterday()) + 1)
                .day(DateUtil.dayOfMonth(DateUtil.yesterday())));
        if (ObjectUtils.isEmpty(yesterdayDeviceStat)) {
            yesterdayDeviceStat = new DeviceStatEntity();
            yesterdayDeviceStat.initAttrValue();
            yesterdayDeviceStat.setSiteId(siteId);
            yesterdayDeviceStat.setYear(DateUtil.year(DateUtil.yesterday()));
        }
        try {

            //获取设备总数
            List<DeviceEntity> deviceList = this.find(new DeviceQuery().siteId(siteId));
            Integer deviceTotalCount = deviceList.size();

            //未激活数量
            Long deviceUnActiveCount = deviceList.parallelStream()
                    .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.未激活.getValue())
                    .count();
            //激活设备
            Integer deviceActiveCount = deviceList.size() - deviceUnActiveCount.intValue();

            deviceStatEntity.setDeviceTotalCount(deviceTotalCount);
            deviceStatEntity.setDeviceAddCount(deviceTotalCount - yesterdayDeviceStat.getDeviceTotalCount());

            ///统计按当前站点归集 // TODO: 2022/8/22
            Rest<List<SitePdu>> resp = siteFeign.getFlatSitesBySiteId(new SitePdu().id(siteId));
//            SitePdu sitePdu = new SitePdu();
//            sitePdu.setSize(-1);
//            Rest<RespData<List<SitePdu>>> resp = siteFeign.list(sitePdu);
//
            if (resp.getCode() == 1) {
                List<SitePdu> sitePduList = resp.getData();
                deviceStatEntity.setSiteTotalCount(sitePduList.size());
                deviceStatEntity.setSiteAddCount(sitePduList.size() - yesterdayDeviceStat.getSiteTotalCount());
            }

            //在线数量
            Long deviceOnlineCount = deviceList.parallelStream()
                    .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                    .filter(f -> f.getEnabled() == EnabledEnum.启用.getValue())
                    .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.在线.getValue())
                    .count();
            deviceStatEntity.setDeviceOnlineCount(deviceOnlineCount.intValue());
            //在线率=在线设备/所有激活设备
            if (deviceActiveCount > 0) {
                deviceStatEntity.setDeviceOnlineRatio(new BigDecimal(deviceOnlineCount).divide(new BigDecimal(deviceActiveCount), ROUND_HALF_DOWN).setScale(2));
            }

            //离线数量
            Long deviceOfflineCount = deviceList.parallelStream()
                    .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                    .filter(f -> f.getEnabled() == EnabledEnum.启用.getValue())
                    .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.离线.getValue())
                    .count();
            deviceStatEntity.setDeviceOfflineCount(deviceOfflineCount.intValue());
            if (deviceActiveCount > 0) {
                deviceStatEntity.setDeviceOfflineRatio(new BigDecimal(deviceOfflineCount).divide(new BigDecimal(deviceActiveCount), ROUND_HALF_DOWN).setScale(2));
            }
            //停用数量
            Long deviceStopCount = deviceList.parallelStream()
                    .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                    .filter(f -> f.getEnabled() == YesNoEnum.NO.getValue())
                    .count();
            deviceStatEntity.setDeviceStopCount(deviceStopCount.intValue());
            if (deviceActiveCount > 0) {
                deviceStatEntity.setDeviceStopRatio(new BigDecimal(deviceStopCount).divide(new BigDecimal(deviceActiveCount), ROUND_HALF_DOWN).setScale(2));
            }


            deviceStatEntity.setDeviceUnActiveCount(deviceUnActiveCount.intValue());
            if (deviceActiveCount > 0) {
                deviceStatEntity.setDeviceUnActiveRatio(new BigDecimal(deviceUnActiveCount).divide(new BigDecimal(deviceActiveCount), ROUND_HALF_DOWN).setScale(2));
            }

            //今日告警数量
            DeviceAlarmInfoQuery deviceAlarmInfoQuery = new DeviceAlarmInfoQuery();
            deviceAlarmInfoQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
            deviceAlarmInfoQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());
            List<DeviceAlarmInfoEntity> deviceAlarmInfoList = deviceAlarmInfoService.find(deviceAlarmInfoQuery);
            deviceStatEntity.setAlarmTotalCount(deviceAlarmInfoList.size());
            deviceStatEntity.setAlarmAddCount(deviceAlarmInfoList.size() - yesterdayDeviceStat.getAlarmTotalCount());

            //推送数量
            AlarmSmsSendQuery alarmSmsSendQuery = new AlarmSmsSendQuery();
            alarmSmsSendQuery.setSendTimeStart(DateUtils.getCurrStrDate());
            alarmSmsSendQuery.setSendTimeEnd(DateUtils.getCurrStrDate());
            alarmSmsSendQuery.setSendStatus(SendStatusEnum.发送成功.getValue());

            List<AlarmSmsSendEntity> alarmSmsSendEntities = alarmSmsSendService.find(alarmSmsSendQuery);
            deviceStatEntity.setPushTotalCount(alarmSmsSendEntities.size());
            deviceStatEntity.setPushAddCount(alarmSmsSendEntities.size() - yesterdayDeviceStat.getPushTotalCount());

            //上行下行数量
            DeviceLogQuery deviceLogQuery = new DeviceLogQuery();
            deviceLogQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
            deviceLogQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());
            Map<Boolean, Long> collect = deviceLogService.find(deviceLogQuery).parallelStream().collect(Collectors.partitioningBy(x -> x.getLogType() == LogTypeEnum.上报事件.getValue(), counting()));
            deviceStatEntity.setUploadMessageTotalCount(collect.getOrDefault(true, 0L).intValue());
            deviceStatEntity.setDownloadMessageTotalCount(collect.getOrDefault(false, 0L).intValue());


            deviceStatEntity.setSiteId(siteId);

            if (deviceStatEntity.newEntity()) {
                deviceStatEntity.setCreateTime(new Date());
                deviceStatService.save(deviceStatEntity);
            } else {
                deviceStatEntity.setUpdateTime(new Date());
                deviceStatService.update(deviceStatEntity);
            }

        } catch (Exception e) {
            log.error("统计异常", e);
            throw new AppException("统计异常!");
        }
    }

    @Override
    public List<DeviceMapEntity> deviceMap(DeviceEntity query, Context context) {
        Rest<SitePdu> info = siteFeign.info(query.getSiteId());
        if (info.getCode() == YesNoEnum.YES.getValue()) {
            SitePdu sitePdu = info.getData();

            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.get(item.getKey());
                        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.00005);
            BigDecimal latiStep = new BigDecimal(0.00005);

            String longitude = sitePdu.getLongitude();
            String latitude = sitePdu.getLatitude();

            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;
        }
        throw new AppException("获取站点信息失败！");
    }

    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        Arrays.asList(ids).stream().forEach(id -> {
            DeviceEntity deviceEntity = this.get(id, context);
            if (!ObjectUtils.isEmpty(deviceEntity)) {
                TbQueueCallback callback = new TbQueueCallback() {
                    @Override
                    public void onSuccess(TbQueueMsgMetadata metadata) {
                        log.info("队列删除成功");
                    }

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

                    }
                };
                messageService.delQueue(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode(), callback);
                messageService.delQueue(Constant.DOWN_TOPIC + deviceEntity.getDeviceCode(), callback);

                PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
                ProductEntity productEntity = productService.get(deviceEntity.getProductId());
                if (!ObjectUtils.isEmpty(platformEntity) && !ObjectUtils.isEmpty(productEntity)) {
                    //新增设备通知第三方平台
                    sendThirdParty(deviceEntity, productEntity, platformEntity, DeviceMethodEnum.DEL);
                }
                //删除扩展extKey
                this.removeCache(deviceEntity.getDeviceCode());
            }
        });
        super.removeBefore(ids, context);
    }

    @Override
    protected void exportAfter(DeviceEntity params, Context context, List<DeviceEntity> list) throws AppException {
        list.stream().forEach(deviceEntity -> {
            PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
            ProductEntity productEntity = productService.get(deviceEntity.getProductId());
            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 {
        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.get(productEntity.getPlatformId());
                    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.get(productEntity.getPlatformId());
                    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())) {
            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());
            }
        }
        updateDeviceHomeUrl(entity);
        super.saveBefore(entity, context);
    }

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

    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 (!entity.getSiteId().equals(temp.getSiteId())) {
                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());
                }
            } else {
                if (ObjectUtils.isEmpty(entity.getSiteCode()) || ObjectUtils.isEmpty(entity.getSiteName())) {
                    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());
                    }
                }
            }
        }
    }

    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());


    }


}