package com.tofly.xrtygis.custom.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.xrtygis.custom.entity.dto.StaitemDto;
import com.tofly.xrtygis.custom.entity.dto.StanderdDto;
import com.tofly.xrtygis.custom.entity.dto.StationDto;
import com.tofly.xrtygis.custom.mapper.CustomDisplayMapper;
import com.tofly.xrtygis.custom.service.CustomScadaAboutService;
import com.tofly.xrtygis.custom.util.CommonMethod;
import com.tofly.xrtygis.em.Constant;
import com.tofly.xrtygis.em.ExcelExportFileTypeEnum;
import com.tofly.xrtygis.entity.Scadahistory;
import com.tofly.xrtygis.entity.Scadastaitem;
import com.tofly.xrtygis.entity.Scadastation;
import com.tofly.xrtygis.service.ScadastaitemService;
import com.tofly.xrtygis.service.ScadastationService;
import com.tofly.xrtygis.strategy.ExcelStrategyContext;
import com.tofly.xrtygis.util.ExcelUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * scada相关
 *
 * @author 陈浩
 */
@Service
@AllArgsConstructor
public class CustomScadaAboutServiceImpl implements CustomScadaAboutService {

    private static final Integer MAX_VALUE = 2 << 10;
    private static final Integer MIN_VALUE = -2 << 10;
    private final ScadastationService scadastationService;
    private final ScadastaitemService scadastaitemService;
    private final CustomDisplayMapper customDisplayMapper;
    private final ExcelStrategyContext excelStrategyContext;

    /**
     * 模糊查询站点名
     *
     * @param stnm 站点名称
     * @return list
     */
    @Override
    public List likeStnm(String stnm) {
        return scadastationService.list(Wrappers.<Scadastation>lambdaQuery()
                .eq(Scadastation::getState, 1)
                .like(stnm != null, Scadastation::getStnm, stnm)
                .select(Scadastation::getId, Scadastation::getStnm, Scadastation::getLgtd, Scadastation::getLttd, Scadastation::getIscraft));
    }

    /**
     * 查看趋势
     *
     * @param stid      站点名称
     * @param itnm      指标项
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return list
     */
    @Override
    public Page viewHistory(Page page, Long stid, String itnm, String startTime, String endTime) {

        Scadastaitem staitem = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                .select(Scadastaitem::getItcd)
                .eq(Scadastaitem::getState, 1)
                .eq(Scadastaitem::getStationId, stid)
                .eq(Scadastaitem::getItnm, itnm));

        Scadastation station = scadastationService.getById(stid);

        if (staitem == null) {
            throw new ToflyDeniedException("测站<" + station.getStnm() + ">未绑定指标：" + itnm);
        }

        return customDisplayMapper.viewHistory(page, staitem.getItcd(), startTime, endTime);
    }

    @Override
    public List<Map> viewHistory(Long stid, String itnm, String startTime, String endTime) {
        Scadastaitem staitem = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .select(Scadastaitem::getItcd)
                .eq(Scadastaitem::getStationId, stid)
                .eq(Scadastaitem::getItnm, itnm));

        Scadastation station = scadastationService.getById(stid);

        if (staitem == null) {
            throw new ToflyDeniedException("测站<" + station.getStnm() + ">未绑定指标：" + itnm);
        }

        return customDisplayMapper.viewHistory2(staitem.getItcd(), startTime, endTime);
    }


    /**
     * 计算合格率
     *
     * @param itcd      指标编号
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return map
     */
    @Override
    public Map calItemValue(String itcd, String startTime, String endTime, Double duration) {
        //指标表
        Scadastaitem staitem = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .eq(Scadastaitem::getItcd, itcd));

        if (null == staitem) {
            throw new ToflyDeniedException("该指标不存在");
        }

        Map<String, Object> result = new HashMap<>(3);

        Map<String, Double> passRate = null;
        if (staitem.getDownLimit() != null || staitem.getUpLimit() != null) {

            double up = staitem.getUpLimit() == null ? MAX_VALUE : staitem.getUpLimit();
            double down = staitem.getDownLimit() == null ? MIN_VALUE : staitem.getDownLimit();

            passRate = calRate(startTime, endTime, staitem.getItcd(), up, down, Long.parseLong(duration.toString()));
        }

        Map<String, Double> qualityRate = null;
        if (null != staitem.getQualityStandard()) {

            String[] split = staitem.getQualityStandard().split(",");

            Double up;
            Double down;
            if (split.length != 0) {
                if (split.length != 2) {
                    if (staitem.getQualityStandard().trim().startsWith(",")) {
                        up = Double.parseDouble(split[1]);
                        down = Double.valueOf(MIN_VALUE);
                    } else {
                        down = Double.parseDouble(split[0]);
                        up = Double.valueOf(MAX_VALUE);
                    }
                } else {
                    up = Double.parseDouble(split[1]);
                    down = Double.parseDouble(split[0]);
                }
                qualityRate = calRate(startTime, endTime, staitem.getItcd(), up, down, Long.parseLong(duration.toString()));
            }
        }

        result.put("passRate", passRate);
        result.put("qualityRate", qualityRate);
        result.put("overStandardNum", getOverStandardNum(staitem, startTime, endTime, duration));

        return result;
    }


    /**
     * 添加测站信息
     *
     * @param scadastation 测站信息表
     * @return true or false
     */
    @Override
    public boolean insertStation(Scadastation scadastation) {

        if (scadastation == null) {
            throw new ToflyDeniedException("插入信息不能为空");
        }
        scadastationService.save(scadastation);

        return true;
    }

    /**
     * 修改测站信息
     *
     * @param scadastation 测站信息
     * @return true or false
     */
    @Override
    public boolean updateStation(Scadastation scadastation) {
        return scadastationService.updateById(scadastation);
    }

    /**
     * 删除测站信息
     *
     * @param ids 测站id
     * @return true or false
     */
    @Override
    public boolean deleteStation(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        scadastationService.removeByIds(list);
        scadastaitemService.remove(Wrappers.<Scadastaitem>lambdaQuery().in(Scadastaitem::getStationId, list));
        return true;
    }

    /**
     * 查看测站信息
     *
     * @param stnm 测站名称
     * @param stcd 测站编号
     * @return page
     */
    @Override
    public List selectStation(Long id, String stnm, String stcd, String categoryName) {

        return scadastationService.list(Wrappers.<Scadastation>lambdaQuery()
                .eq(id != null, Scadastation::getId, id)
                .eq(Scadastation::getState, 1)
                .like(!StringUtils.isEmpty(categoryName), Scadastation::getCategoryName, categoryName)
                .like(!StringUtils.isEmpty(stnm), Scadastation::getStnm, stnm)
                .like(!StringUtils.isEmpty(stcd), Scadastation::getStcd, stcd)
                .orderByAsc(Scadastation::getSn));
    }

    @Override
    public Page selectStation(Page page, Long id, String stnm, String stcd, String categoryName) {
        return scadastationService.page(page, Wrappers.<Scadastation>lambdaQuery()
                .eq(id != null, Scadastation::getId, id)
                .eq(Scadastation::getState, 1)
                .like(!StringUtils.isEmpty(categoryName), Scadastation::getCategoryName, categoryName)
                .like(!StringUtils.isEmpty(stnm), Scadastation::getStnm, stnm)
                .like(!StringUtils.isEmpty(stcd), Scadastation::getStcd, stcd)
                .orderByAsc(Scadastation::getSn));
    }

    /**
     * 添加指标信息
     *
     * @param item 指标配置信息
     * @return true or false
     */
    @Override
    public boolean insertIndex(Scadastaitem item) {
        Scadastaitem scadastaitem = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .eq(Scadastaitem::getItcd, item.getItcd()));

        //编号为空新增;不为空测站id为空修改
        if (scadastaitem == null) {
            scadastaitemService.save(item);
        } else if (scadastaitem.getStationId() == null) {
            Long id = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                    .eq(Scadastaitem::getItcd, item.getItcd())).getId();

            item.setId(id);

            scadastaitemService.updateById(item);
        } else {
            throw new ToflyDeniedException("该指标已绑定测站");
        }
        return true;
    }

    /**
     * 修改测站指标
     *
     * @param item 测站信息
     * @return true or false
     */
    @Override
    public boolean updateIndex(Scadastaitem item) {
        if (item.getStationId() != null) {
            throw new ToflyDeniedException("不能更改测站信息");
        }

        return scadastaitemService.updateById(item);
    }

    /**
     * 查询未关联指标
     *
     * @param itcd 指标编号
     * @return list
     */
    @Override
    public List viewIndex(String itcd) {

        return scadastaitemService.list(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .like(Scadastaitem::getItcd, itcd)
                .isNull(Scadastaitem::getStationId)
                .select(Scadastaitem::getItcd, Scadastaitem::getItnm));
    }

    /**
     * 删除测站指标表
     *
     * @param ids 指标id
     * @return true or false
     */
    @Override
    public boolean deleteIndex(String ids) {
        return scadastaitemService.removeByIds(Arrays.asList(ids.split(",")));
    }

    /**
     * 查看测站指标表
     *
     * @param ids 测站id
     * @return page
     */
    @Override
    public List selectIndex(String ids) {
        return scadastaitemService.list(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .in(Scadastaitem::getStationId, Arrays.asList(ids.split(","))));
    }

    /**
     * 获取测站名称
     *
     * @return list
     */
    @Override
    public List getStnm() {
        return scadastationService.list(Wrappers.<Scadastation>lambdaQuery().select(Scadastation::getStnm));
    }

    /**
     * 获取指标名
     *
     * @param stnm 测站名
     * @return list
     */
    @Override
    public List getItnm(String stnm) {
        Long stationId = scadastationService.getOne(Wrappers.<Scadastation>lambdaQuery()
                .eq(Scadastation::getStnm, stnm)).getId();

        return scadastaitemService.list(Wrappers.<Scadastaitem>lambdaQuery()
                .eq(Scadastaitem::getState, 1)
                .eq(Scadastaitem::getStationId, stationId)
                .select(Scadastaitem::getItnm, Scadastaitem::getIscalcPass,
                        Scadastaitem::getPassStandard, Scadastaitem::getIscalcQuality,
                        Scadastaitem::getQualityStandard));
    }

    /**
     * 获取超标次数
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param time      超时时间
     * @return double
     */
    @Override
    public Double getOverStandardNum(Scadastaitem statiem, String startTime, String endTime, Double time) {

        double up = statiem.getUpLimit() == null ? MAX_VALUE : statiem.getUpLimit();
        double down = statiem.getDownLimit() == null ? MIN_VALUE : statiem.getDownLimit();

        //查询对应数据
        List<Scadahistory> historyList = customDisplayMapper.viewItValue(statiem.getItcd(), startTime, endTime);

        //是否超标
        boolean flag = false;
        //超标开始时长
        Date start = null;
        //超标结束时长
        Date end = null;
        //超标次数
        double num = 0D;

        int size = historyList.size() - 1;

        for (int i = 0; i <= size; i++) {
            Scadahistory item = historyList.get(i);
            //指标值
            double itVal = Double.parseDouble(item.getItval());
            //没超标时
            if (!flag) {
                //当超标更改标记并设置开始时间，没超标更改结束时间
                if (itVal > up || itVal < down) {
                    flag = true;
                    start = item.getScadaTime();
                }

                //当标记为超标时
            } else {
                //数据未超标将标记改为未超标
                if (itVal < up && itVal > down) {
                    flag = false;
                    end = historyList.get(i - 1).getScadaTime();
                }
            }

            if (item.getScadaTime() == historyList.get(size).getScadaTime()) {
                end = item.getScadaTime();
            }

            //当开始时间和结束时间不为空计算
            if (start != null && end != null) {
                double floor = Math.floor(((end.getTime() - start.getTime()) / 1000 / 60) / (time * 60));
                if (floor >= 1) {
                    num += floor;
                }
                //重置开始时间和状态
                start = null;
                flag = false;
                end = null;
            }
            if (i == size) {
                if (!flag && end == null) {
                    num += 1;
                }
            }
        }
        return num;
    }

    /**
     * 测站指标上传
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    public boolean stationExport(String dto) {
        if (dto.isEmpty()) {
            throw new ToflyDeniedException("dto is not null");
        }
        List<StationDto> station = JSONObject.parseArray(dto, StationDto.class).stream()
                .distinct().collect(Collectors.toList());

        Map<String, List<StaitemDto>> dtoMap = JSONObject.parseArray(dto, StaitemDto.class).stream().collect(Collectors.groupingBy(StaitemDto::getStcd));

        station.forEach(tion -> {
            Scadastation stion = scadastationService.getOne(Wrappers.<Scadastation>lambdaQuery()
                    .eq(Scadastation::getStcd, tion.getStcd()));

            Long stId = null;
            if (null == stion) {
                Scadastation scadastation = JSONObject.parseObject(JSONObject.toJSONString(tion), Scadastation.class);
                scadastation.setState("1");
                scadastationService.save(scadastation);
                stId = scadastation.getId();
            }
            if (dtoMap != null && null != dtoMap.get(tion.getStcd())) {
                List<StaitemDto> staitemDtos = dtoMap.get(tion.getStcd());

                if (null != staitemDtos && staitemDtos.size() > 0) {
                    Long finalStId = stId;
                    JSONObject.parseArray(JSONObject.toJSONString(staitemDtos), Scadastaitem.class)
                            .forEach(it -> {

                                Scadastaitem statiem = scadastaitemService.getOne(Wrappers.<Scadastaitem>lambdaQuery()
                                        .eq(Scadastaitem::getItcd, it.getItcd()));
                                if (statiem != null) {
                                    it.setId(statiem.getId());
                                    scadastaitemService.updateById(it);
                                } else {
                                    if (finalStId != null) {
                                        it.setStationId(finalStId);
                                    } else if (stion != null) {
                                        it.setStationId(stion.getId());
                                    }
                                    it.setState(1L);
                                    scadastaitemService.save(it);
                                }

                            });
                }
            }
        });
        return true;
    }

    @Override
    public List<Map> getIndexType() {
        return customDisplayMapper.getIndexType();
    }

    /**
     * 批量配置测站指标标准
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    public boolean insertStandard(StanderdDto dto) {
        if (dto == null) {
            throw new ToflyDeniedException("数据为空");
        }

        return scadastaitemService.update(Wrappers.<Scadastaitem>lambdaUpdate()
                .eq(Scadastaitem::getStationId, dto.getStationId())
                .set(dto.getUpLimit() != null, Scadastaitem::getUpLimit, dto.getUpLimit())
                .set(dto.getDownLimit() != null, Scadastaitem::getDownLimit, dto.getDownLimit())
                .set(dto.getUpLimit() != null || dto.getDownLimit() != null, Scadastaitem::getIscalcPass, 1)
                .set(dto.getQualityStandard() != null, Scadastaitem::getQualityStandard, dto.getQualityStandard()));
    }

    /**
     * 获取已配置合格率/优质率的测站与指标信息
     *
     * @return map
     */
    @Override
    public Map<Object, List<Map>> getStationItemInfo() {
        List<Map> stationItemInfo = customDisplayMapper.getStationItemInfo();
        if (!stationItemInfo.isEmpty()) {
            return stationItemInfo.stream().collect(Collectors.groupingBy(m -> m.get("stnm")));
        } else {
            return null;
        }

    }

    /**
     * 趋势分析
     *
     * @param itcd  指标编号
     * @param start 开始时间
     * @param end   结束时间
     * @param time  超时时间
     * @param itid  需排除id
     * @return map
     */
    @Override
    public Map<String, Double> trendAnalys(String itcd, String start, String end, Double time, String itid) {
        Map<String, Double> result = new HashMap<>();
        //指标编号分割
        List<String> itcdList = Arrays.asList(itcd.split(","));
        //查询指标信息并根据指标编号分组
        Map<String, List<Scadastaitem>> itemList = scadastaitemService.list(Wrappers.<Scadastaitem>lambdaQuery()
                .in(Scadastaitem::getItcd, itcdList)
                .eq(Scadastaitem::getState, 1))
                .stream().collect(Collectors.groupingBy(Scadastaitem::getItcd));

        if (itemList != null && !itemList.isEmpty()) {
            List<String> itidList = StringUtils.isEmpty(itid) ? null : Arrays.asList(itid.split(","));

            //查询指标历史
            Map<Object, List<Map<String, Object>>> itvalList = customDisplayMapper.getItvalHistory(itcdList, start, end, itidList)
                    .stream().collect(Collectors.groupingBy(map -> map.get("itcd")));
            //超标开始时间
            Date startDate = null;
            //超标结束时间
            Date endDate = null;
            //超标标志
            boolean flag = false;
            //超标时长
            double qualityTimeOut = 0;
            //超标次数
            double qualityNum = 0;
            //优质标准
            Double quaDown = null;
            Double quaUp = null;

            //同上，合格率
            double limitTimeOut = 0;
            double limitNum = 0;
            Double limitDown = null;
            Double limitUp = null;

            //分析总时长
            long sumTime = ((DateUtil.formatDate(end, "yyyy-MM-dd HH:mm:ss").getTime() - DateUtil.formatDate(start, "yyyy-MM-dd HH:mm:ss").getTime()) / 1000 / 60 / 60) * itcdList.size();
            double totalTime = (double) sumTime;

            for (String cd : itcdList) {

                //单个指标信息
                Scadastaitem item = itemList.get(cd).get(0);
                //优质标准
                String qualityStandard = item.getQualityStandard();
                //数值信息
                List<Map<String, Object>> maps = itvalList.get(cd);
                if (maps != null){
                    int size = maps.size() - 1;
                    //优质率不为空且不为，
                    if (!StringUtils.isEmpty(qualityStandard)) {
                        if (!",".equals(qualityStandard.trim())) {
                            String[] split = qualityStandard.split(",");
                            //优质上限值、下限值和实际值
                            quaDown = StringUtils.isEmpty(split[0]) ? MIN_VALUE : Double.parseDouble(split[0]);
                            quaUp = StringUtils.isEmpty(split[1]) ? MAX_VALUE : Double.parseDouble(split[1]);
                        }
                    }
                    //合格率标识为1赋值
                    if ("1".equals(item.getIscalcPass())) {
                        //合格上下限
                        limitUp = item.getUpLimit() == null ? MAX_VALUE : item.getUpLimit();
                        limitDown = item.getDownLimit() == null ? MIN_VALUE : item.getDownLimit();
                    }

                    for (int i = 0; i <= size; i++) {
                        double itval = Double.parseDouble(maps.get(i).get("itval").toString());
                        //计算优质率 给予赋值后计算
                        if (quaDown != null && quaUp != null) {
                            if ((itval < quaDown || itval > quaUp) && !flag) {
                                startDate = DateUtil.formatDate(maps.get(i).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                flag = true;
                            } else if ((itval > quaDown && itval < quaUp) && flag) {
                                endDate = DateUtil.formatDate(maps.get(i - 1).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                flag = false;
                            }

                            if (i == size) {
                                if (flag && endDate == null) {
                                    flag = false;
                                    endDate = DateUtil.formatDate(maps.get(i).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                }
                            }

                            if (startDate != null && endDate != null && !flag) {
                                double cal = Double.parseDouble(String.format("%.2f", (endDate.getTime() - startDate.getTime() + 0.0) / 1000 / 60 / 60));
                                qualityTimeOut += cal;
                                startDate = null;
                                endDate = null;
                                if (cal / (time * 60) >= 1) {
                                    qualityNum += 1;
                                }
                            }
                        }
                        //计算合格率 同上
                        if (limitDown != null && limitUp != null) {
                            if ((itval < limitDown || itval > limitUp) && !flag) {
                                startDate = DateUtil.formatDate(maps.get(i).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                flag = true;
                            } else if ((itval > limitDown && itval < limitDown) && flag) {
                                endDate = DateUtil.formatDate(maps.get(i - 1).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                flag = false;
                            }

                            if (i == size) {
                                if (flag && endDate == null) {
                                    flag = false;
                                    endDate = DateUtil.formatDate(maps.get(i).get("scadaTime").toString(), "yyyy-MM-dd HH:mm:ss");
                                }
                            }

                            if (startDate != null && endDate != null && !flag) {
                                double cal = Double.parseDouble(String.format("%.2f", (endDate.getTime() - startDate.getTime() + 0.0) / 1000 / 60 / 60));
                                limitTimeOut += cal;
                                startDate = null;
                                endDate = null;
                                if (cal / (time * 60) >= 1) {
                                    limitNum += 1;
                                }
                            }
                        }
                    }
                }
            }
            if (quaDown != null && quaUp != null) {
                result.put("qualityRete", Double.parseDouble(String.format("%.2f", 100 - ((qualityTimeOut / totalTime) * 100))));
                result.put("qualityNum", qualityNum);
                result.put("qualityTimeOut", qualityTimeOut);
            }
            if (limitDown != null && limitUp != null) {
                result.put("limitRete", Double.parseDouble(String.format("%.2f", 100 - ((limitTimeOut / totalTime) * 100))));
                result.put("limitNum", limitNum);
                result.put("limitTimeOut", limitTimeOut);
            }
            result.put("totalTime", totalTime);
        }
        return result;
    }

    /**
     * 获取指标历史
     *
     * @param itcd  指标编号
     * @param start 开始时间
     * @param end   结束时间
     * @return map
     */
    @Override
    public Map<Object, List<Map<String, Object>>> getValHistory(String itcd, String start, String end) {
        return customDisplayMapper.getItvalHistory(Arrays.asList(itcd.split(",")), start, end, null)
                .stream().collect(Collectors.groupingBy(map -> map.get("itcd")));
    }

    /**
     * 获取指标历史
     *
     * @param page  page
     * @param itcd  指标编号
     * @param start 开始时间
     * @param end   结束时间
     * @return map
     */
    @Override
    public Map<Object, Page> getValHistory(Page page, String itcd, String start, String end) {
        Map<Object, Page> result = new HashMap<>();
        Map<Object, List<Map<String, Object>>> valHistory = this.getValHistory(itcd, start, end);
        for (String cd : itcd.split(",")) {
            if (!valHistory.isEmpty()){
                result.put(cd, CommonMethod.listToPage(page, valHistory.get(cd)));
            }else {
                result.put(cd,page);
            }
        }
        return result;
    }

    /**
     * 单个指标历史分页查询
     *
     */
    @Override
    public Page<Map> itvalPageQuery(Page page, String itcd, String start, String end) {
        return customDisplayMapper.viewHistory(page, itcd, start, end);
    }

    /**
     * 指标历史导出
     *
     * @param itcd  指标编号
     * @param start 开始时间
     * @param end   结束时间
     */
    @Override
    public Object itemValExport(HttpServletResponse response, String itcd, String start, String end) {
        List<Map<String, Object>> itvalHistory = customDisplayMapper.itemValInfo(Arrays.asList(itcd.split(",")), start, end);
        // 根据templateServiceType,templateFlag获取对应模板数据
        ExcelExportFileTypeEnum excelExportFileTypeEnum = ExcelExportFileTypeEnum.getExcelExportFileTypeEnum("itemItvalExportService", "1");
        if (null == excelExportFileTypeEnum) {
            throw new ToflyDeniedException("导出失败");
        }
        //将查询的结果转json字符串的格式，因为导出的时候只能传一个字符串
        String resultListToString = JSONArray.toJSONStringWithDateFormat(itvalHistory, "yyyy-MM-dd HH:mm:ss");
        // 从模型类型枚举根据templateServiceType获取策略对应模板数据
        List<Map<String, Object>> dataList = excelStrategyContext.getExportData("itemItvalExportService", "1", resultListToString);
        ExcelUtil.export(dataList.get(0), excelExportFileTypeEnum, Constant.FILE_PATH_TEST_EXPORT_EXCEL, response);
        return null;
    }

    private Map<String, Double> calRate(String startTime, String endTime, String itcd, Double up, Double down, Long duration) {
        Date startDate = DateUtil.formatDate(startTime, "yyyy-MM-dd HH:mm:ss");
        Date endDate = DateUtil.formatDate(endTime, "yyyy-MM-dd HH:mm:ss");

        //总时长
        long sumTime = (endDate.getTime() - startDate.getTime()) / 1000 / 60 / (duration * 60);
        //超标标识
        boolean flag = false;
        //超标时长
        double time = 0D;
        //开始时长
        Date start = null;
        //结束时长
        Date end = null;

        Map<String, Double> map = new HashMap<>();

        List<Scadahistory> valueList = customDisplayMapper.viewItValue(itcd, startTime, endTime);

        if (valueList.size() >= 1) {
            int size = valueList.size() - 1;

            for (int i = 0; i <= size; i++) {
                Scadahistory item = valueList.get(i);
                //指标值
                double itVal = Double.parseDouble(item.getItval());
                //没超标时
                if (!flag) {
                    //当超标更改标记并设置开始时间，没超标更改结束时间
                    if (itVal > up || itVal < down) {
                        flag = true;
                        start = item.getScadaTime();
                    }

                    //当标记为超标时
                } else {
                    //数据未超标将标记改为未超标
                    if (itVal < up && itVal > down) {
                        flag = false;
                        end = valueList.get(i - 1).getScadaTime();
                    }
                }

                if (item.getScadaTime() == valueList.get(size).getScadaTime()) {
                    end = item.getScadaTime();
                }

                //当开始时间和结束时间不为空计算
                if (start != null && end != null) {

                    time += Math.floor((double) ((end.getTime() - start.getTime()) / 1000 / 60 / (duration * 60)));
                    //重置开始时间和状态
                    start = null;
                    flag = false;
                    end = null;
                }
                if (i == size) {
                    if (!flag && end == null) {
                        if (start == null) {
                            continue;
                        }
                        time += Math.floor((double) ((valueList.get(i).getScadaTime().getTime() - start.getTime()) / 1000 / 60 / (duration * 60)));
                    }
                }
            }
            map.put("rate", Double.parseDouble(new DecimalFormat("0.00").format(100 - (time / sumTime) * 100)));
            map.put("sumTime", time);
        } else {
            map.put("rate", null);
            map.put("sumTime", null);
        }


        return map;
    }

}
