package com.huatek.busi.task.curve.helper;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.google.common.collect.Lists;
import com.huatek.busi.common.util.DateUtil;
import com.huatek.busi.common.util.DecimalUtil;
import com.huatek.busi.dto.curve.BaseCurveQueryDto;
import com.huatek.busi.dto.curve.PointItemDto;
import com.huatek.busi.service.curve.BaseCurveSensorService;
import com.huatek.busi.service.curve.CurveSensorEntityService;
import com.huatek.busi.vo.curve.PointItemVo;

/**
 * 告警二级界面曲线定时任务抽象类
 * 
 * @author anker_cheng
 * @date 2019/08/31
 */
public abstract class AbstractCurveTask implements CurveTask {
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    protected final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE);

    @Autowired
    protected CurveSensorEntityService curveSensorEntityService;

    @Override
    public void execute() {
        LocalDate yesterday = LocalDate.now().minusDays(1);
        execute(yesterday);
    }

    @Override
    public void execute(String params) {
        LocalDate day = LocalDate.parse(params, FORMATTER);
        execute(day);
    }

    protected void execute(BaseCurveSensorService service, LocalDate yesterday, String subType) {
        List<BaseCurveQueryDto> sensorCodeList = service.findSensorCodeList(yesterday);
        if (CollectionUtils.isEmpty(sensorCodeList)) {
            logger.debug("{}-{}-{}无sensor 数据", yesterday, service.getClass().getName(), subType);
            return;
        }
        for (BaseCurveQueryDto baseCurve : sensorCodeList) {
            baseCurve.setSubType(subType);
            // 小于六条，直接保存
            if (baseCurve.getCount() == null || baseCurve.getCount() == 0) {
                continue;
            }
            if (baseCurve.getCount() <= service.pointCountPerDay()) {
                List<PointItemVo> daylyPointList = service.findDaylyPointList(baseCurve, yesterday, subType);
                curveSensorEntityService.doExecute(baseCurve, yesterday, subType, daylyPointList);
                continue;
            }
            //大于六条，分段统计
            List<LocalDateTime> timeList = timeList(yesterday);
            List<PointItemVo> daylyPointList = Lists.newArrayListWithCapacity(service.pointCountPerDay());
            for (int i = 0; i < service.pointCountPerDay(); i++) {
                baseCurve.setStartTime(timeList.get(i));
                baseCurve.setEndTime(timeList.get(i + 1));
                PointItemDto daylyPointStatistics = service.getDaylyPointStatistics(baseCurve);
                if(isEmpty(daylyPointStatistics)) {
                	continue;
                }
                if (daylyPointStatistics.getCount() == 0) {
                    continue;
                }
                // 总条数大于等于3条，去掉最大值和最小值，再求平均值
                if (daylyPointStatistics.getCount() >= 3) {
                    daylyPointStatistics.setTotal(daylyPointStatistics.getTotal()
                        .subtract(daylyPointStatistics.getMax()).subtract(daylyPointStatistics.getMin()));
                    daylyPointStatistics.setCount(daylyPointStatistics.getCount() - 2);
                }
                PointItemVo point = new PointItemVo();
                point.setMainTreeId(baseCurve.getMainTreeId());
                point.setSensorCode(baseCurve.getSensorCode());
                point.setTimeStamp(baseCurve.getEndTime());
                point.setVal(DecimalUtil.divide(daylyPointStatistics.getTotal(),
                    BigDecimal.valueOf(daylyPointStatistics.getCount()), 4));
                daylyPointList.add(point);
            }
            curveSensorEntityService.doExecute(baseCurve, yesterday, subType, daylyPointList);
        }
    }

    static List<LocalDateTime> timeList(LocalDate yesterday) {
        List<LocalDateTime> list = Lists.newArrayList();
        for (int i = 0; i < 7; i++) {
            if(i == 0) {
                list.add(yesterday.atStartOfDay());
                continue;
            }
            list.add(list.get(i - 1).plusHours(4));
        }
        return list;
    }
    
    static boolean isEmpty(PointItemDto item) {
    	return item == null || item.getCount() == null || item.getMax() == null || item.getMin() == null
    			|| item.getTotal() == null || StringUtils.isEmpty(item.getMainTreeId());
    }

//    protected void execute(BaseCurveSensorService service, LocalDate yesterday, String subType) {
//        int pointCountPerDay = service.pointCountPerDay();
//        List<BaseCurveQueryDto> sensorCodeList = service.findSensorCodeList(yesterday);
//        if (CollectionUtils.isEmpty(sensorCodeList)) {
//            logger.debug("{}无sensor 数据", yesterday);
//            return;
//        }
//        // 统计当天每个sensor的数据总量
//        for (BaseCurveQueryDto baseCurve : sensorCodeList) {
//            List<PointItemVo> daylyPointList = service.findDaylyPointList(baseCurve, yesterday, subType);
//            int per = daylyPointList.size() / pointCountPerDay;
//            if (per == 0) {
//                curveSensorEntityService.doExecute(baseCurve, yesterday, subType, daylyPointList);
//                continue;
//            }
//            logger.debug("sensor: {} {} total: {}, pointCountPerDay: {}", baseCurve.getSensorCode(), yesterday,
//                daylyPointList.size(), pointCountPerDay);
//            List<PointItemVo> newPointList = Lists.newArrayListWithCapacity(pointCountPerDay);
//            Stream.iterate(0, n -> n + 1).limit(pointCountPerDay).forEach(i -> {
//                int limit = per;
//                if (i == pointCountPerDay - 1) {
//                    limit = daylyPointList.size() - i * per;
//                }
//                List<PointItemVo> list =
//                    daylyPointList.stream().skip(i * per).limit(limit).collect(Collectors.toList());
//                logger.debug("##{}, list: {}", i, list);
//                // 小于三个点直接求取平均值
//                if (list.size() >= 3) {
//                    Optional<PointItemVo> max = list.stream().max((a, b) -> a.getVal().compareTo(b.getVal()));
//                    Optional<PointItemVo> min = list.stream().min((a, b) -> a.getVal().compareTo(b.getVal()));
//                    logger.debug("remove max: {}, min: {}", max.orElse(null), min.orElse(null));
//                    list.removeAll(Arrays.asList(max.orElse(null), min.orElse(null)));
//                }
//                // 时间
//                LocalDateTime timeStamp = list.get(list.size() - 1).getTimeStamp();
//                // 求平均值
//                BigDecimal sum = list.stream().map(PointItemVo::getVal).reduce(BigDecimal.ZERO, BigDecimal::add);
//                newPointList.add(new PointItemVo(baseCurve.getSensorCode(), timeStamp,
//                    DecimalUtil.divide(sum, BigDecimal.valueOf(list.size()), 2)));
//            });
//            curveSensorEntityService.doExecute(baseCurve, yesterday, subType, newPointList);
//        }
//    }
}