package com.jiayue.ipfcst.service;

import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.data.entity.ElectricField;
import com.jiayue.ipfcst.common.data.entity.ForecastPowerShortTermTwo;
import com.jiayue.ipfcst.common.data.repository.ForecastPowerShortTermTwoRepository;
import com.jiayue.ipfcst.common.data.repository.PowerStationStatusDataRepository;
import com.jiayue.ipfcst.common.data.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 短期预测实时业务层(一期)
 *
 * @author yh
 * @version 1.0
 * @since 2019/8/5 16:02
 */
@Service
public class ForecastPowerShortTermTwoService extends BaseService {

  private final ForecastPowerShortTermTwoRepository ForecastPowerShortTermTwoRepository;
  private final PowerStationStatusDataRepository powerStationStatusDataRepository;

  @Autowired
  public ForecastPowerShortTermTwoService(ForecastPowerShortTermTwoRepository ForecastPowerShortTermTwoRepository, PowerStationStatusDataRepository powerStationStatusDataRepository) {
    this.ForecastPowerShortTermTwoRepository = ForecastPowerShortTermTwoRepository;
    this.powerStationStatusDataRepository = powerStationStatusDataRepository;
  }

  /**
   * 按时间查询实时预测短期 yh
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @return 结果集
   */

  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public Map<String, Object> findByForecastTimeBetween(Long startTime, Long endTime) throws BusinessException {
    Map<String, Object> map = new HashMap<>();
    ElectricField electricField = super.getElectricField();
    map.put("cap",electricField.getCapacity());
    List<ForecastPowerShortTermTwo> list = new ArrayList<>();
    list = ForecastPowerShortTermTwoRepository.findByForecastTimeBetween(startTime, endTime);
    list.sort(Comparator.comparing(ForecastPowerShortTermTwo::getForecastTime));

    long startTimeLong = startTime;
    long endTimeLong = endTime;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    long timeStep = 900000L;
    if (startTimeLong % timeStep != 0) {
      startTimeLong = startTimeLong - (startTimeLong % timeStep)+timeStep;
    }
    List<Float> datas = new ArrayList<>();
    List<String> times = new ArrayList<>();

    for (long i = startTimeLong; i < endTimeLong; i = i + timeStep) {
      long finalI = i;
      List<ForecastPowerShortTermTwo> p = list.stream().filter(t -> t.getForecastTime() == finalI).collect(Collectors.toList());
      if (p != null && p.size() > 0) {
        datas.add(p.get(0).getFpValue().floatValue());
      } else {
        datas.add(null);
      }
      String timeFormat = sdf.format(new Date(i));
      times.add(timeFormat);
    }
    map.put("times", times);
    map.put("datas", datas);
    return map;
  }


  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public Map<String, Object> findByForecastTimeBetweenForComprehensive(Long startTime, Long endTime,Long timeStep) throws BusinessException {
    Map<String, Object> map = new HashMap<>();
    List<ForecastPowerShortTermTwo> list = new ArrayList<>();
    list = ForecastPowerShortTermTwoRepository.findByForecastTimeBetween(startTime, endTime);
    list.sort(Comparator.comparing(ForecastPowerShortTermTwo::getForecastTime));

    long startTimeLong = startTime;
    long endTimeLong = endTime;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    if (startTimeLong % timeStep != 0) {
      startTimeLong = startTimeLong - (startTimeLong % timeStep)+timeStep;
    }
    List<Float> datas = new ArrayList<>();
    List<String> times = new ArrayList<>();

    for (long i = startTimeLong; i < endTimeLong; i = i + timeStep) {
      long finalI = i;
      List<ForecastPowerShortTermTwo> p = list.stream().filter(t -> t.getForecastTime() == finalI).collect(Collectors.toList());
      if (p != null && p.size() > 0) {
        datas.add(p.get(0).getFpValue().floatValue());
      } else {
        datas.add(null);
      }
      String timeFormat = sdf.format(new Date(i));
      times.add(timeFormat);
    }
    map.put("times", times);
    map.put("datas", datas);
    return map;
  }

  /**
   * 根据时间 分页查询 实时预测短期数据 yh
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @param page      页码
   * @param size      条数
   * @param sortOrder 排序
   * @return
   */
  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public Map<String, Object> findByTimeBetweenAndNoForPaging(Long startTime, Long endTime,
                                                             Integer page, Integer size,
                                                             String sortOrder) {
    Map<String, Object> map = new HashMap<>();
    Sort sort = Sort.by(Sort.Direction.DESC, "forecastTime");
    if (sortOrder.contains("asc")) {
      sort = Sort.by(Sort.Direction.ASC, "forecastTime");
    }
    Specification<ForecastPowerShortTermTwo> specification = this.specificationFindByTimeAndNo(startTime, endTime);
    Pageable pageable = PageRequest.of(page - 1, size, sort);
    Page forecastPowerShortTerms = ForecastPowerShortTermTwoRepository.findAll(specification, pageable);
    List<ForecastPowerShortTermTwo> datas = new ArrayList<>();
    datas = forecastPowerShortTerms.getContent();
    map.put("content", datas);
    map.put("count", forecastPowerShortTerms.getTotalElements());
    return map;
  }

  /**
   * 根据时间和编号 分页查询条件 yh
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @return 过滤条件
   */
  Specification<ForecastPowerShortTermTwo> specificationFindByTimeAndNo(final Long startTime, final Long endTime) {
    return (Specification<ForecastPowerShortTermTwo>) (root, criteriaQuery, cb) -> {
      List<Predicate> predicates = new ArrayList<>();
      if (startTime != null) {
        //大于或等于传入时间
        predicates.add(cb.greaterThanOrEqualTo(root.get("forecastTime").as(Long.class), startTime));
      }
      if (endTime != null) {
        //小于传入时间
        predicates.add(cb.lessThan(root.get("forecastTime").as(Long.class), endTime));
      }

      //添加排序的功能
      return cb.and(predicates.toArray(new Predicate[predicates.size()]));

    };
  }

  /**
   * 查询回传数据
   * @param stTime         开始时间
   * @param eTime          结束时间
   * @return
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public String[] findSendData(Long stTime,Long eTime,List<ForecastPowerShortTermTwo> list){

    List<ForecastPowerShortTermTwo> collect = list.stream().filter(s -> s.getForecastTime() >= stTime && s.getForecastTime() <= eTime).collect(Collectors.toList());
    String[] datas = new String[list.size()];
    if(null != collect && collect.size() > 0){
      int index = 0;
      for(ForecastPowerShortTermTwo f:collect){
        datas[index] = String.valueOf(f.getFpValue());
        index++;
      }
    }
    return datas;
  }

  @Transactional(propagation = Propagation.REQUIRED)
  public List<ForecastPowerShortTermTwo> findSendDataForTimeBetween(Long stTime,Long eTime){
    return ForecastPowerShortTermTwoRepository.findByForecastTimeBetween(stTime,eTime);
  }

}
