package com.casic.missiles.modular.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.casic.missiles.config.DeviceServerProperties;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.core.base.service.IBaseExportService;
import com.casic.missiles.core.datascope.DataScope;
import com.casic.missiles.model.response.SuccessResponseData;
import com.casic.missiles.modular.system.constant.DeviceConfigConst;
import com.casic.missiles.modular.system.dao.BusConfigMapper;
import com.casic.missiles.modular.system.dto.BusConfigDTO;
import com.casic.missiles.modular.system.dto.DeviceTypeEnum;
import com.casic.missiles.modular.system.model.BusConfig;
import com.casic.missiles.modular.system.model.Device;
import com.casic.missiles.modular.system.redis.RedisPublisherUtil;
import com.casic.missiles.modular.system.rs.RedisCommon;
import com.casic.missiles.modular.system.service.IBusConfigService;
import com.casic.missiles.modular.system.service.IDeviceRuleService;
import com.casic.missiles.modular.system.service.IDeviceService;
import com.casic.missiles.util.RegUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;

/**
 * <p>
 * 设备配置表 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2019-05-16
 */
@Service
public class BusTubeConfigServiceImpl extends ServiceImpl<BusConfigMapper, BusConfig> implements IBusConfigService {
    @Autowired
    private RedisCommon redisCommon;
    @Resource
    private IBaseExportService exportService;
    @Autowired
    private IDeviceService iDeviceService;
    @Autowired
    private IDeviceRuleService iDeviceRuleService;
    @Autowired
    private DeviceServerProperties deviceServerProperties;

    @Override
    public List<BusConfig> getListBydevId(Long devId) {
        QueryWrapper<BusConfig> busConfigEntityWrapper = new QueryWrapper<>();
        busConfigEntityWrapper.eq("DEVICE_ID", devId);
        return this.baseMapper.selectList(busConfigEntityWrapper);
    }

    public String getThresholdByDevId(BusConfigDTO busConfigDTO) {
        String limitValue = "0";//报警阈值
        limitValue = getWellDeepByDevId(busConfigDTO.getDeviceId());
        DecimalFormat df = new DecimalFormat("0.000");
        limitValue = df.format(Double.parseDouble(limitValue) *
                Double.valueOf(busConfigDTO.getPercent()) / 100);
        return limitValue;
    }

    @Override
    public List<BusConfigDTO> getConfigList(Page<BusConfigDTO> page,
                                            String keywords,
                                            String deptid,
                                            Long deviceType,
                                            DataScope dataScope) {
        List<Map<String, Object>> result = this.baseMapper.getConfigList(page, keywords, deptid,
                BusConfigDTO.sensorHashMap.get(deviceType.intValue()), dataScope);
        List<BusConfigDTO> busConfigDTOList = new ArrayList<>();
        for (Map<String, Object> objectMap : result) {
            BusConfigDTO dto = BusConfigDTO.ConvertDTO(objectMap);
            String framecontent = objectMap.get("framecontent").toString();
            if (null != framecontent) {
                String[] configItems = framecontent.split(",");
                dto.setRetryTimes(configItems[0]);
                dto.setCollectInterval(configItems[1]);
                dto.setUploadPeriod(configItems[2]);
                if (configItems.length == 5) {
                    dto.setIp(configItems[3]);
                    dto.setPort(configItems[4]);
                }
            }
            busConfigDTOList.add(dto);
        }
        return busConfigDTOList;

    }


    @Override
    public String getConcenCodeByDevId(Long devID) {
        return this.baseMapper.getConcenCodeByDevId(devID);
    }

    @Override
    public String getWellDeepByDevId(Long devID) {
        return this.baseMapper.getWellDeepByDevId(devID);
    }

    @Transactional
    @Override
    public void addConfig(BusConfigDTO busConfigDTO) {
        List<BusConfig> busConfigList = getListBydevId(busConfigDTO.getDeviceId());
        busConfigList.forEach(busConfig -> {
            this.removeById(busConfig.getId());
        });
        busConfigDTO.setDeviceType(Long.valueOf(DeviceTypeEnum.Tube.getIndex()));
        BusConfig busConfig = new BusConfig(busConfigDTO);
        String str = busConfigDTO.getRetryTimes() + "," + busConfigDTO.getCollectInterval() + ","
                + busConfigDTO.getUploadPeriod() + ","
                + busConfigDTO.getIp() + "," + busConfigDTO.getPort();//按照重传次数、采集间隔、上传周期
        busConfig.setFramecontent(str);
        save(busConfig);
        String concentratorCode = redisCommon.sendMsg(DeviceTypeEnum.Tube.toString(),
                busConfig.getDeviceId(), busConfig.getFramecontent(), busConfigDTO.getAttemptsMax());
        //发布消息订阅
        if (StrUtil.isNotBlank(concentratorCode)) {
            RedisPublisherUtil.getInstance().
                    publishMessage(concentratorCode);
        }
    }

    @Transactional
    public void addBatchConfig(List<BusConfigDTO> busConfigDTOList) {
        String concentratorCodeStr = "";
        for (BusConfigDTO busConfigDTO : busConfigDTOList) {
            List<BusConfig> busConfigList = getListBydevId(busConfigDTO.getDeviceId());
            for (BusConfig busConfig : busConfigList) {
                removeById(busConfig.getId());
            }
            busConfigDTO.setDeviceType(Long.valueOf(DeviceTypeEnum.Tube.getIndex()));
            BusConfig busConfig1 = new BusConfig(busConfigDTO);
            String str = busConfigDTO.getRetryTimes() + "," + busConfigDTO.getCollectInterval() + ","
                    + busConfigDTO.getUploadPeriod() + ","
                    + busConfigDTO.getIp() + "," + busConfigDTO.getPort();//按照重传次数、采集间隔、上传周期
            busConfig1.setFramecontent(str);
            save(busConfig1);
            String concentratorCode = redisCommon.sendMsg(DeviceTypeEnum.Tube.toString(),
                    busConfig1.getDeviceId(), busConfig1.getFramecontent(), busConfigDTO.getAttemptsMax());
            if (StrUtil.isNotBlank(concentratorCode)) {
                concentratorCodeStr += (concentratorCode + ",");
            }
        }
        if (StrUtil.isNotBlank(concentratorCodeStr)) {//发布消息订阅
            RedisPublisherUtil.getInstance().
                    publishMessage(concentratorCodeStr.substring(0, concentratorCodeStr.length() - 1));
        }
    }

    @Override
    public void updateConfig(BusConfigDTO busConfigDTO) {
        busConfigDTO.setThreshold(Float.valueOf(getThresholdByDevId(busConfigDTO)));
        BusConfig busConfig = getById(busConfigDTO.getId());
        busConfig.setDeviceId(Long.valueOf(busConfigDTO.getDeviceId()));
        busConfig.setFramecontent(busConfigDTO.getThreshold() + "," + busConfigDTO.getInstallHeight() + ","
                + busConfigDTO.getRetryTimes() + "," + busConfigDTO.getPercent() + "," + busConfigDTO.getIp() + ","
                + busConfigDTO.getPort());
        busConfig.setStatus("0");
        busConfig.setAttemptsmax(Integer.valueOf(busConfigDTO.getAttemptsMax()));
        busConfig.setWritetime(new Date());
        updateById(busConfig);
        Device device = iDeviceService.getById(busConfigDTO.getDeviceId());
        if (device != null) {
            iDeviceRuleService.updateRule(device.getDevcode(), busConfigDTO.getThreshold(), null);
        }
        String concentratorCode = redisCommon.sendMsg(DeviceTypeEnum.Liquid.toString(),
                busConfig.getDeviceId(), busConfig.getFramecontent(), busConfigDTO.getAttemptsMax());
        if (StrUtil.isNotBlank(concentratorCode)) {//发布消息订阅
            RedisPublisherUtil.getInstance().
                    publishMessage(concentratorCode);
        }
    }

    public Map<String, Object> validate(List<BusConfigDTO> busConfigDTOList) {
        Map<String, Object> stringMap = new HashMap<>();
        try {
            for (int i = 0; i < busConfigDTOList.size(); i++) {

                if (!RegUtil.isInteger(busConfigDTOList.get(i).getUploadPeriod())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，上传周期必填且为正整数");
                    return stringMap;

                }
                if (!RegUtil.isNumOrLetter(busConfigDTOList.get(i).getDevcode())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，设备编号必填且为字母或数字");
                    return stringMap;
                } else {//校验设备编号是否在系统中存在
                    Device device = iDeviceService.getDeviceByDevCode(
                            busConfigDTOList.get(i).getDevcode());
                    if (null == device) {
                        stringMap.put("success", false);
                        stringMap.put("msg", "第" + (i + 2) + "行，设备编号在系统中不存在，请先导入设备");
                        return stringMap;
                    } else {
                        busConfigDTOList.get(i).setDeviceId(device.getId());
                    }
                }

                if (!RegUtil.isInteger(busConfigDTOList.get(i).getRetryTimes())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，重传次数必填且为正整数");
                    return stringMap;
                }
                if (!RegUtil.isInteger(busConfigDTOList.get(i).getCollectInterval())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，采集间隔必填且为正整数");
                    return stringMap;
                }

                if (!RegUtil.isIp(busConfigDTOList.get(i).getIp())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，IP填写不合格");
                    return stringMap;
                }
                if (!RegUtil.isPort(busConfigDTOList.get(i).getPort())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，端口号填写不合格");
                    return stringMap;
                }
                if (!RegUtil.isInteger(busConfigDTOList.get(i).getAttemptsMax())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，最大尝试次数必填且为正整数");
                    return stringMap;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            stringMap.put("success", false);
            stringMap.put("msg", "导入异常！");
        }
        stringMap.put("success", true);
        stringMap.put("msg", "导入成功");
        return stringMap;
    }

    @Transactional
    @Override
    public SuccessResponseData imp(MultipartFile uploadFile) {
        SuccessResponseData resultData = new SuccessResponseData();
        Map<String, String> mapper = new HashMap<>();
        mapper.put("设备编号", "devcode");
        mapper.put("重传次数", "retryTimes");
        mapper.put("上传周期（分）", "uploadPeriod");
        mapper.put("采集间隔（分）", "collectInterval");
        mapper.put("IP地址", "ip");
        mapper.put("端口号", "port");
        mapper.put("最大尝试次数", "attemptsMax");
        List<BusConfigDTO> busConfigDTOList = new ArrayList<>();
        try {
            busConfigDTOList = exportService.importExcel(BusConfigDTO.class, uploadFile, null, null);
            Map<String, Object> objectMap = this.validate(busConfigDTOList);
            if ((Boolean) objectMap.get("success")) {//检验通过后写入
                this.addBatchConfig(busConfigDTOList);
                resultData.setCode(200);
                resultData.setMessage(objectMap.get("msg").toString());
            } else {//校验失败，返回
                resultData.setCode(400);
                resultData.setMessage(objectMap.get("msg").toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            resultData.setCode(400);
            resultData.setMessage("导入失败");
        }
        return resultData;
    }

    @Override
    public void exp(List<BusConfigDTO> busConfigDTOList, HttpServletResponse response) {
        FileInputStream fis = null;
        try {
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", " attachment;filename=".concat(DeviceConfigConst.METHANE_CONFIG_EXPORT_TEMP));
            if (CollectionUtil.isEmpty(busConfigDTOList)) {
                fis = new FileInputStream(deviceServerProperties.getExportPath().concat(DeviceConfigConst.CONFIG_EXPORT_EMPTY_TEMP));
            } else {
                fis = new FileInputStream(deviceServerProperties.getExportPath().concat(DeviceConfigConst.METHANE_CONFIG_EXPORT_TEMP));
            }
            Map<String, Object> var = new HashMap<>();
            var.put("list", new ArrayList<Object>() {
                {
                    for (int i = 0; i < busConfigDTOList.size(); i++) {
                        BusConfigDTO busConfigDTO = busConfigDTOList.get(i);
                        add(new HashMap<String, Object>() {
                            {
                                put("设备编号", busConfigDTO.getDevcode());
                                put("重传次数", busConfigDTO.getRetryTimes());
                                put("采集间隔", busConfigDTO.getCollectInterval());
                                put("上传周期", busConfigDTO.getUploadPeriod());
                                put("IP地址", busConfigDTO.getIp());
                                put("端口", busConfigDTO.getPort());
                                put("最大尝试次数", busConfigDTO.getAttemptsMax());
                                put("已尝试次数", busConfigDTO.getAttemptsCurrent());
                                put("下发状态", "1".equals(busConfigDTO.getStatus()) ? "已下发" : "未下发");
                            }
                        });
                    }
                }
            });
            //输出模板
            exportService.exportExcel(response, BusConfigDTO.class, busConfigDTOList, "导出文件");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.getOutputStream().flush();
                response.getOutputStream().close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
