package com.njcn.gather.tool.wave.utils;

import com.njcn.gather.tool.wave.pojo.bo.InstantData;
import com.njcn.gather.tool.wave.pojo.bo.RmsData;
import com.njcn.gather.tool.wave.pojo.bo.WaveDataDetail;
import com.njcn.gather.tool.wave.pojo.dto.WaveDataDTO;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 波形明细组装工具。
 */
public final class WaveUtil {

    /** 单相展示颜色。 */
    private static final List<String> ONE_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#fff", "#fff"));
    /** 两相展示颜色。 */
    private static final List<String> TWO_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#2E8B57", "#fff"));
    /** 三相展示颜色。 */
    private static final List<String> THREE_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#2E8B57", "#A52a2a"));

    private WaveUtil() {
    }

    /**
     * 将原始波形结果整理成前端查看明细。
     *
     * @param waveDataDTO 波形结果数据
     * @return 波形明细列表
     */
    public static List<WaveDataDetail> filterWaveData(WaveDataDTO waveDataDTO) {
        List<WaveDataDetail> waveDataDetails = new ArrayList<>();
        List<String> waveTitle = waveDataDTO.getWaveTitle();
        List<String> channelNames = waveDataDTO.getChannelNames();
        int phaseCount = waveDataDTO.getIPhasic();
        boolean openTri = waveDataDTO.getPtType() != null && waveDataDTO.getPtType() == 2;
        int picCount = (waveTitle.size() - 1) / phaseCount;

        for (int i = 0; i < picCount; i++) {
            WaveDataDetail detail = buildBaseDetail(waveTitle, channelNames, phaseCount, i);
            float ratio = resolveRatio(waveDataDTO, waveTitle.get(phaseCount * i + 1), detail);

            detail.setInstantData(buildInstantData(waveDataDTO.getListWaveData(), waveTitle, phaseCount, i, ratio, openTri));
            detail.setRmsData(buildRmsData(waveDataDTO.getListRmsData(), waveTitle, phaseCount, i, ratio, openTri));
            detail.setIsOpen(openTri);
            waveDataDetails.add(detail);
        }
        return waveDataDetails;
    }

    /**
     * 构建单组波形的基础明细信息。
     */
    private static WaveDataDetail buildBaseDetail(List<String> waveTitle, List<String> channelNames, int phaseCount, int index) {
        WaveDataDetail detail = new WaveDataDetail();
        switch (phaseCount) {
            case 1:
                detail.setA(waveTitle.get(index + 1).substring(1));
                detail.setB("");
                detail.setC("");
                detail.setChannelName(channelNames.get(index + 1));
                detail.setColors(new ArrayList<>(ONE_PHASE_COLORS));
                break;
            case 2:
                detail.setA(waveTitle.get(index * 2 + 1).substring(1));
                detail.setB(waveTitle.get(index * 2 + 2).substring(1));
                detail.setC("");
                detail.setChannelName(channelNames.get(index * 2 + 1));
                detail.setColors(new ArrayList<>(TWO_PHASE_COLORS));
                break;
            case 3:
            default:
                detail.setA(waveTitle.get(index * 3 + 1).substring(1));
                detail.setB(waveTitle.get(index * 3 + 2).substring(1));
                detail.setC(waveTitle.get(index * 3 + 3).substring(1));
                detail.setChannelName(channelNames.get(index * 3 + 1));
                detail.setColors(new ArrayList<>(THREE_PHASE_COLORS));
                break;
        }
        return detail;
    }

    /**
     * 根据标题判断比例和单位。
     */
    private static float resolveRatio(WaveDataDTO waveDataDTO, String title, WaveDataDetail detail) {
        if (title.substring(0, 1).equalsIgnoreCase("U")) {
            detail.setUnit("kV");
            return waveDataDTO.getPt().floatValue() / 1000;
        }
        detail.setUnit("A");
        return waveDataDTO.getCt().floatValue();
    }

    /**
     * 构建 RMS 明细数据。
     */
    private static RmsData buildRmsData(List<List<Float>> sourceData, List<String> waveTitle, int phaseCount, int index,
                                        float ratio, boolean openTri) {
        List<List<Float>> aValues = new ArrayList<>();
        List<List<Float>> bValues = new ArrayList<>();
        List<List<Float>> cValues = new ArrayList<>();
        float max = Float.NEGATIVE_INFINITY;
        float min = Float.POSITIVE_INFINITY;

        if (sourceData == null) {
            sourceData = Collections.emptyList();
        }

        for (List<Float> row : sourceData) {
            if (row == null || row.isEmpty()) {
                continue;
            }
            Float x = row.get(0);
            if (x == null) {
                continue;
            }
            float valueA = 0f;
            float valueB = 0f;
            float valueC = 0f;
            boolean existsA = false;
            boolean existsB = false;
            boolean existsC = false;

            for (int m = 0; m < phaseCount; m++) {
                String currentTitle = waveTitle.get(phaseCount * index + m + 1).substring(1);
                int valueIndex = phaseCount * index + m + 1;
                if (row.size() <= valueIndex) {
                    continue;
                }
                Float sourceValue = row.get(valueIndex);
                Float value = sourceValue == null ? null : sourceValue * ratio;
                if (currentTitle.contains("A")) {
                    if (value != null) {
                        valueA = value;
                        existsA = true;
                    }
                    aValues.add(buildPoint(x, value));
                } else if (currentTitle.contains("B")) {
                    if (value != null) {
                        valueB = value;
                        existsB = true;
                    }
                    bValues.add(buildPoint(x, value));
                } else if (currentTitle.contains("C")) {
                    if (value != null) {
                        valueC = value;
                        existsC = true;
                    }
                    cValues.add(buildPoint(x, value));
                }
            }

            if (existsA) {
                max = Math.max(max, valueA);
                min = Math.min(min, valueA);
            }
            if (existsB) {
                max = Math.max(max, valueB);
                if (!openTri) {
                    min = Math.min(min, valueB);
                }
            }
            if (existsC) {
                max = Math.max(max, valueC);
                min = Math.min(min, valueC);
            }
        }

        RmsData data = new RmsData();
        data.setAValue(aValues);
        data.setBValue(bValues);
        data.setCValue(cValues);
        data.setMax(max == Float.NEGATIVE_INFINITY ? 0f : max);
        data.setMin(min == Float.POSITIVE_INFINITY ? 0f : min);
        return data;
    }

    /**
     * 构建单个点位。
     */
    private static List<Float> buildPoint(Float x, Float y) {
        List<Float> point = new ArrayList<>(2);
        point.add(x);
        point.add(y);
        return point;
    }

    /**
     * 基于瞬时数据构建明细对象。
     */
    private static InstantData buildInstantData(List<List<Float>> sourceData, List<String> waveTitle, int phaseCount, int index,
                                                float ratio, boolean openTri) {
        RmsData rmsData = buildRmsData(sourceData, waveTitle, phaseCount, index, ratio, openTri);
        InstantData instantData = new InstantData();
        instantData.setAValue(rmsData.getAValue());
        instantData.setBValue(rmsData.getBValue());
        instantData.setCValue(rmsData.getCValue());
        instantData.setMax(rmsData.getMax());
        instantData.setMin(rmsData.getMin());
        return instantData;
    }
}
