package com.cpp.web.service.datafactory.impl;

import com.cpp.web.domain.datafactory.BaseParsing;
import com.cpp.web.domain.datafactory.ParsingCdq;
import com.cpp.web.domain.datafactory.dto.ParsingConfParam;
import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
import com.cpp.web.domain.station.ForecastPowerUltraShortTermStation;
import com.cpp.web.service.datafactory.ParsingCdqService;
import com.cpp.web.service.datafactory.ParsingInterface;
import com.cpp.web.service.station.ForecastPowerUltraShortTermStationService;
import com.cpp.web.utils.ParsingFieldUtil;
import com.cpp.web.utils.ParsingFileUtil;
import com.cpp.web.utils.ParsingUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 超短期解析业务层实现类
 *
 * @author tl
 * @date 2022-05-11 18:07:03
 */
@Service("rcdqParsing")
@AllArgsConstructor
@Slf4j
@Transactional
public class ParsingRcdqServiceImpl implements ParsingInterface {

    private final ForecastPowerUltraShortTermStationService forecastPowerUltraShortTermStationService;

    private final ParsingCdqService parsingCdqService;

    private List<ParsingCdq> parsingCdqs = new ArrayList<>();

    @Override
    public boolean save(BaseParsing parsingInfo) {
        return true;
    }

    @Override
    public boolean deleteById(Long id) {
        return true;
    }

    @Override
    public ParsingResultDto parsing(File file, String stationCode) {

        ParsingResultDto parsingResultDto = new ParsingResultDto();
        parsingResultDto.setFileName(file.getName());
        parsingResultDto.setFileType(FileTypeEnum.cdq.name());

        try {
            List<ForecastPowerUltraShortTermStation> forecastPowerUltraShortTermStationList = new ArrayList();

            if (!this.parsingCdqs.isEmpty()) {
                ParsingCdq parsingCdq = this.parsingCdqs.get(0);

                List<String> fileContent = ParsingFileUtil.getFileContent(file);
                if (parsingCdq.getDataType().equals(ParsingFieldUtil.MULTI)) {//多行操作
                    Date forecastTime = parsingForecastTime(parsingCdq.getForecastTime(), fileContent);
                    Date time = forecastTime;
                    if (forecastTime != null) {//解析时间成功才可以进行以下操作
                        if (parsingCdq.getFpValue() != null) {
                            List<BigDecimal> fpValues = parsingFpValue(parsingCdq.getFpValue(), fileContent);
                            if (fpValues.size() > 0) {
                                BigDecimal openCapacity = parsingValue(parsingCdq.getOpenCapacity(), fileContent);
                                for (BigDecimal fpValue : fpValues) {
                                    ForecastPowerUltraShortTermStation forecastPowerUltraShortTermStation = new ForecastPowerUltraShortTermStation();
                                    forecastPowerUltraShortTermStation.setStationCode(stationCode);
                                    forecastPowerUltraShortTermStation.setFpValue(fpValue);
                                    forecastPowerUltraShortTermStation.setTime(time);
                                    forecastPowerUltraShortTermStation.setForecastHowLongAgo(calcHowLongAgo(forecastTime, time));
                                    forecastPowerUltraShortTermStation.setOpenCapacity(openCapacity);
                                    forecastPowerUltraShortTermStationList.add(forecastPowerUltraShortTermStation);
                                    time = new Date(time.getTime() + 900000L);//递增15分钟
                                }
                                forecastPowerUltraShortTermStationService.saveBatch(forecastPowerUltraShortTermStationList);
                                log.info("解析 调控后CDQ文件：{} 成功！ O(∩_∩)O", file.getName());
                                parsingResultDto.setStatus("success");
                            } else {
                                parsingResultDto.setMessage("解析超短期文件时间错误");
                                log.error("解析 调控后CDQ文件时间错误");
                            }
                        } else {
                            parsingResultDto.setMessage("调控后超短期文件中时间无法解析");
                            log.error("调控后cdq文件里日期不对");
                        }

                    } else {
                        parsingResultDto.setMessage("解析 调控后超短期文件无数据");
                        log.error("解析 调控后超短期文件无数据");
                    }
                } else {
                    parsingResultDto.setMessage("调控后超短期暂无单行解析方式");
                    log.error(" 调控后cdq暂无单行解析方式");
                }
            }

        } catch (Exception e) {
            parsingResultDto.setMessage("解析 调控后超短期数据失败!");
            log.error("解析 调控后超短期数据失败！ /(ㄒoㄒ)/~~", e);
        } finally {
            return parsingResultDto;
        }
    }

    @Override
    public boolean activationParsingConf() {
        this.parsingCdqs = parsingCdqService.list();
        return true;
    }

    //解析预测时间
    protected Date parsingForecastTime(String sign, List<String> fileContent) {
        Date forecastTime = null;
        try {
            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);

            String s = fileContent.get(ParsingUtil.noParseInt(config.getLineNumber()));
            int signIndex = s.indexOf(config.getDataSign());
            String result;
            if (signIndex > 0) {
                int startLength = config.getDataSign().length() + signIndex + 1;
                int length = config.getFormat().length();
                if (String.valueOf(s.charAt(startLength + 1)).equals("'")) {
                    startLength += 1;
                }
                result = s.substring(startLength, startLength + length);

                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(config.getFormat());

                forecastTime = simpleDateFormat.parse(result);

                log.info("解析 调控后超短期【预测时间】成功，开始时间为：{}", result);
            } else {
                log.error("解析 调控后超短期【预测时间】时公式标识不存在所在行");
            }

        } catch (RuntimeException e) {
            log.error("解析 调控后超短期【预测时间】失败");
            e.printStackTrace();
        } finally {
            return forecastTime;
        }

    }


    /*
     * 解析配置格式规则：
     *   s=>>1=>>entity=
     *   s：单行标识
     *   1：取值在1行
     *   entity=：键标记标记
     *
     *   m=>>4-20=>>3
     *   m：多行标识
     *   4-20：取值在4-20行
     *   3：第三列
     * */
    protected List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
        List<BigDecimal> fpValues = new ArrayList<>();
        try {
            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);


            String[] lineNumber = config.getLineNumber().split("-");
            int startLine = ParsingUtil.noParseInt(lineNumber[0]);
            int endLine = ParsingUtil.noParseInt(lineNumber[1]);

            for (int i = startLine; i <= endLine; i++) {
                String[] strings = ParsingUtil.splitLineWithSpace(fileContent.get(i));
                String result = strings[ParsingUtil.noParseInt(config.getRowNumber())];

                fpValues.add(new BigDecimal(result));
            }

            log.info("解析 调控后超短期【预测数据】成功！！！，记录数：{}", fpValues.size());

        } catch (RuntimeException e) {
            log.error("解析 调控后超短期【预测数据】失败");
            e.printStackTrace();
        } finally {
            return fpValues;
        }
    }

    /**
     * 计算D+x中的x
     *
     * @param baseTime
     * @param time
     */
    public Integer calcHowLongAgo(Date baseTime, Date time) {
        return ((int) ((time.getTime() - baseTime.getTime()) / 900000L)) + 1;
    }

}
