package com.iailab.module.model.mcs.pre.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.util.date.DateUtils;
import com.iailab.module.model.mcs.pre.dao.MmItemResultDao;
import com.iailab.module.model.mcs.pre.entity.MmItemResultEntity;
import com.iailab.module.model.mcs.pre.entity.MmItemResultJsonEntity;
import com.iailab.module.model.mcs.pre.service.MmItemResultService;
import com.iailab.module.model.mdk.vo.DataValueVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author PanZhibao
 * @date 2021年05月28日 10:34
 */
@Service
public class MmItemResultServiceImpl extends ServiceImpl<MmItemResultDao, MmItemResultEntity> implements MmItemResultService {

    private final int max_group_count = 100;

    private final String T_MM_ITEM_RESULT = "T_MM_ITEM_RESULT";

    @Autowired
    private MmItemResultDao mmItemResultDao;

    @Override
    public void savePredictValue(Map<String, List<DataValueVO>> predictValueMap, int t, String nIndex, Date predictTime) {
        List<MmItemResultEntity> importList = new ArrayList<>();
        List<MmItemResultEntity> lastList = new ArrayList<>();

        for (Map.Entry<String, List<DataValueVO>> entry : predictValueMap.entrySet()) {
            for (DataValueVO dataVo : entry.getValue()) {
                MmItemResultEntity importData = new MmItemResultEntity();
                importData.setId(String.valueOf(UUID.randomUUID()));
                importData.setOutputid(entry.getKey());
                importData.setDatatime(dataVo.getDataTime());
                importData.setDatavalue(new BigDecimal(dataVo.getDataValue()));
                importList.add(importData);
            }

            List<DataValueVO> lastVoList = new ArrayList<>();
            int size = entry.getValue().size();
            t = Math.max(t, 0);
            int n = "n".equals(nIndex) ? size : Integer.parseInt(nIndex);
            int length = Math.max((n - t), 0); //预测完不变的数据长度
            if (size >= n) {
                for (int i = 0; i < (size - length); i ++) {
                    int index = length + i;
                    lastVoList.add(entry.getValue().get(index));
                }
            } else {
                lastVoList = entry.getValue();
            }

            for (DataValueVO dataVo : lastVoList) {
                MmItemResultEntity importData = new MmItemResultEntity();
                importData.setId(String.valueOf(UUID.randomUUID()));
                importData.setOutputid(entry.getKey());
                importData.setDatatime(dataVo.getDataTime());
                importData.setDatavalue(new BigDecimal(dataVo.getDataValue()));
                lastList.add(importData);
            }

            MmItemResultJsonEntity resultJson = new MmItemResultJsonEntity();
            resultJson.setId(UUID.randomUUID().toString());
            resultJson.setOutputid(entry.getKey());
            resultJson.setPredicttime(predictTime);
            List<Double> jsonValueList = entry.getValue().stream().map(valueVO -> {
                return valueVO.getDataValue();
            }).collect(Collectors.toList());
            resultJson.setJsonvalue(JSONArray.toJSONString(jsonValueList));
            Map<String, Object> map4 = new HashMap(2);
            map4.put("TABLENAME", "T_MM_ITEM_RESULT_JSON");
            map4.put("entity", resultJson);
            mmItemResultDao.savePredictJsonValue(map4);

            Map<String, Object> params = new HashMap(4);
            params.put("TABLENAME", T_MM_ITEM_RESULT);
            params.put("OUTPUTID", entry.getKey());
            params.put("STARTTIME", importList.get(0).getDatatime());
            params.put("ENDTIME", importList.get(importList.size() - 1).getDatatime());
            mmItemResultDao.deletePredictValue(params);
        }
        mmItemResultDao.insertBatch(importList,max_group_count);

        Map<String, Object> map3 = new HashMap<>(2);
        map3.put("TABLENAME", "T_MM_ITEM_RESULT_LAST_POINT");
        map3.put("list", lastList);
        mmItemResultDao.savePredictValue(map3);
    }

    @Override
    public List<DataValueVO> getPredictValue(String outputid, Date startTime, Date endTime) {
        List<DataValueVO> result = new ArrayList<>();
        QueryWrapper<MmItemResultEntity> queryWrapper = new QueryWrapper<MmItemResultEntity>()
                .eq("outputid", outputid)
                .between("datatime", startTime, endTime)
                .orderByAsc("datatime");
        List<MmItemResultEntity> list = mmItemResultDao.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        result = list.stream().map(t -> {
            DataValueVO dv = new DataValueVO();
            dv.setDataTime(t.getDatatime());
            dv.setDataValue(t.getDatavalue().doubleValue());
            return dv;
        }).collect(Collectors.toList());
        return result;
    }

    @Override
    public List<Object[]> getData(String outputid, Date startTime, Date endTime, String timeFormat) {
        List<Object[]> result = new ArrayList<>();
        QueryWrapper<MmItemResultEntity> queryWrapper = new QueryWrapper<MmItemResultEntity>()
                .eq("outputid", outputid)
                .between("datatime", startTime, endTime)
                .orderByAsc("datatime");
        List<MmItemResultEntity> list = mmItemResultDao.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        list.forEach(item -> {
            Object[] dataItem = new Object[2];
            dataItem[0] = DateUtils.format(item.getDatatime(), timeFormat);
            dataItem[1] = item.getDatavalue().setScale(2, BigDecimal.ROUND_HALF_UP);
            result.add(dataItem);
        });
        return result;
    }
}