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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.config.DeviceServerProperties;
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 BusConfigServiceImpl extends ServiceImpl<BusConfigMapper, BusConfig> implements IBusConfigService {
    @Resource
    private IBaseExportService exportService;
    @Autowired
    private RedisCommon redisCommon;

    @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 = getWellDeepByDevId(busConfigDTO.getDeviceId());
        if (StrUtil.isNotBlank(limitValue)) {
            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.setThreshold(null != configItems[0] ?
                        Float.valueOf(configItems[0]) : null);
                dto.setInstallHeight(null != configItems[1] ?
                        Float.valueOf(configItems[1]) : null);
                dto.setRetryTimes(configItems[2]);
                dto.setPercent(null != configItems[3] ?
                        Float.valueOf(configItems[3]) : null);
                if (configItems.length == 6) {
                    dto.setIp(configItems[4]);
                    dto.setPort(configItems[5]);
                }
            }
            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) {
        try {
            List<BusConfig> busConfigList = getListBydevId(busConfigDTO.getDeviceId());
            busConfigList.forEach(busConfig -> {
                this.removeById(busConfig.getId());
            });
            String threshold = getThresholdByDevId(busConfigDTO);
            if (StrUtil.isNotBlank(threshold)) {
                busConfigDTO.setThreshold(Float.valueOf(threshold));
            }
            busConfigDTO.setDeviceType(Long.valueOf(DeviceTypeEnum.Liquid.getIndex()));
            BusConfig busConfig = new BusConfig(busConfigDTO);
            String framecontent = busConfigDTO.getThreshold() + "," + busConfigDTO.getInstallHeight() + ","
                    + busConfigDTO.getRetryTimes() + "," + busConfigDTO.getPercent() + "," + busConfigDTO.getIp() + ","
                    + busConfigDTO.getPort();
            busConfig.setFramecontent(framecontent);
            save(busConfig);
            Device device = iDeviceService.getById(busConfigDTO.getDeviceId());
            if (device != null && StrUtil.isNotBlank(threshold)) {
                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);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @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.setThreshold(Float.valueOf(getThresholdByDevId(busConfigDTO)));
            busConfigDTO.setDeviceType(Long.valueOf(DeviceTypeEnum.Liquid.getIndex()));
            BusConfig busConfig1 = new BusConfig(busConfigDTO);
            String framecontent = busConfigDTO.getThreshold() + "," + busConfigDTO.getInstallHeight() + ","
                    + busConfigDTO.getRetryTimes() + "," + busConfigDTO.getPercent() + "," + busConfigDTO.getIp() + ","
                    + busConfigDTO.getPort();
            busConfig1.setFramecontent(framecontent);
            save(busConfig1);
            Device device = iDeviceService.getById(busConfigDTO.getDeviceId());
            if (device != null) {
                iDeviceRuleService.updateRule(device.getDevcode(), busConfigDTO.getThreshold(), null);
            }
            String concentratorCode = redisCommon.sendMsg(DeviceTypeEnum.Liquid.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));
        }
    }

    @Transactional
    @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.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 (0 == busConfigDTOList.get(i).getPercent()) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，报警阈值必填且小数位最多保留2位");
                    return stringMap;

                } else if (!RegUtil.isDecimal2(String.valueOf(busConfigDTOList.get(i).getPercent()))) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，报警阈值必填且小数位最多保留2位");
                    return stringMap;
                }
                if (!RegUtil.isInteger(busConfigDTOList.get(i).getRetryTimes())) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，重传次数必填且为正整数");
                    return stringMap;
                }
                if (0.0 == busConfigDTOList.get(i).getInstallHeight()) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，安装高度必填且小数位最多保留2位");
                    return stringMap;
                } else if (!RegUtil.isDecimal2(String.valueOf(busConfigDTOList.get(i).getInstallHeight()))) {
                    stringMap.put("success", false);
                    stringMap.put("msg", "第" + (i + 2) + "行，安装高度必填且小数位最多保留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("报警阈值（%）", "percent");
        mapper.put("安装高度（M）", "installHeight");
        mapper.put("重传次数", "retryTimes");
        mapper.put("IP地址", "ip");
        mapper.put("端口号", "port");
        mapper.put("最大尝试次数", "attemptsMax");
        List<BusConfigDTO> busConfigDTOList = new ArrayList<>();

        try {
            //TODO 注解设置
            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 (IOException 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.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.CONFIG_EXPORT_TEMP));
            }
            //TODO BusConfigDTO导出文件注解设置
            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();
            }
        }
    }
}
