package com.njcn.advance.responsibility.model;

import com.njcn.advance.responsibility.constant.CalculationMode;
import com.njcn.advance.responsibility.constant.CalculationStatus;
import com.njcn.advance.responsibility.constant.HarmonicConstants;

/**
 * 谐波数据结构类
 * 对应C语言中的harm_data_struct结构体
 * 
 * @author hongawen
 * @version 1.0
 */
public class HarmonicData {
    
    // 输入参数
    private CalculationMode calculationMode;  // 计算标志
    private int harmonicCount;                // 谐波数据个数
    private int powerCount;                   // 功率数据个数
    private int powerNodeCount;               // 功率负荷节点数
    private int windowSize;                   // 数据窗大小
    private int responsibilityDataCount;      // 代入的责任数据个数
    private float harmonicThreshold;          // 谐波电压门槛
    
    // 数据数组
    private float[] harmonicData;             // 谐波数据序列
    private float[][] powerData;              // 功率数据序列
    
    // 输入输出数据
    private float[][] correlationData;        // 动态相关系数数据序列
    private float[][] fkData;                 // 不包含背景动态谐波责任数据序列
    private float[][] hkData;                 // 包含背景动态谐波责任数据序列
    private float[] canonicalCorrelation;     // 典则相关系数
    private float[] backgroundCanonicalCorr;  // 包含背景典则相关系数
    
    // 输出结果
    private CalculationStatus calculationStatus;  // 计算状态
    private float[] sumFKData;                   // 不包含背景谐波责任
    private float[] sumHKData;                   // 包含背景谐波责任
    
    /**
     * 默认构造函数
     */
    public HarmonicData() {
        this.calculationMode = CalculationMode.FULL_CALCULATION;
        this.calculationStatus = CalculationStatus.NOT_CALCULATED;
        this.windowSize = HarmonicConstants.DEFAULT_WINDOW_SIZE;
    }
    
    /**
     * Builder模式构造器
     */
    public static class Builder {
        private HarmonicData data = new HarmonicData();
        
        public Builder calculationMode(CalculationMode mode) {
            data.calculationMode = mode;
            return this;
        }
        
        public Builder harmonicCount(int count) {
            data.harmonicCount = count;
            return this;
        }
        
        public Builder powerCount(int count) {
            data.powerCount = count;
            return this;
        }
        
        public Builder powerNodeCount(int count) {
            data.powerNodeCount = count;
            return this;
        }
        
        public Builder windowSize(int size) {
            data.windowSize = size;
            return this;
        }
        
        public Builder harmonicThreshold(float threshold) {
            data.harmonicThreshold = threshold;
            return this;
        }
        
        public Builder harmonicData(float[] data) {
            this.data.harmonicData = data;
            return this;
        }
        
        public Builder powerData(float[][] data) {
            this.data.powerData = data;
            return this;
        }
        
        public HarmonicData build() {
            // 验证数据
            validateData();
            // 初始化数组
            initializeArrays();
            return data;
        }
        
        private void validateData() {
            if (data.harmonicCount <= 0 || data.harmonicCount > HarmonicConstants.MAX_HARM_NUM) {
                throw new IllegalArgumentException("Invalid harmonic count: " + data.harmonicCount);
            }
            if (data.powerCount <= 0 || data.powerCount > HarmonicConstants.MAX_P_NUM) {
                throw new IllegalArgumentException("Invalid power count: " + data.powerCount);
            }
            if (data.powerNodeCount <= 0 || data.powerNodeCount > HarmonicConstants.MAX_P_NODE) {
                throw new IllegalArgumentException("Invalid power node count: " + data.powerNodeCount);
            }
            if (data.windowSize < HarmonicConstants.MIN_WIN_LEN || 
                data.windowSize > HarmonicConstants.MAX_WIN_LEN) {
                throw new IllegalArgumentException("Invalid window size: " + data.windowSize);
            }
            
            // 验证数据对齐
            if (data.calculationMode == CalculationMode.FULL_CALCULATION) {
                int ratio = data.harmonicCount / data.powerCount;
                if (ratio * data.powerCount != data.harmonicCount || ratio < 1) {
                    throw new IllegalArgumentException("Harmonic data count must be integer multiple of power data count");
                }
            }
        }
        
        private void initializeArrays() {
            if (data.harmonicData == null) {
                data.harmonicData = new float[data.harmonicCount];
            }
            if (data.powerData == null) {
                data.powerData = new float[data.powerCount][data.powerNodeCount];
            }
            
            int resultCount = data.powerCount - data.windowSize;
            if (resultCount > 0) {
                data.correlationData = new float[resultCount][data.powerNodeCount];
                data.fkData = new float[resultCount][data.powerNodeCount];
                data.hkData = new float[resultCount][data.powerNodeCount + 1];
                data.canonicalCorrelation = new float[resultCount];
                data.backgroundCanonicalCorr = new float[resultCount];
            }
            
            data.sumFKData = new float[data.powerNodeCount];
            data.sumHKData = new float[data.powerNodeCount + 1];
        }
    }
    
    // Getters and Setters
    public CalculationMode getCalculationMode() {
        return calculationMode;
    }
    
    public void setCalculationMode(CalculationMode calculationMode) {
        this.calculationMode = calculationMode;
    }
    
    public int getHarmonicCount() {
        return harmonicCount;
    }
    
    public void setHarmonicCount(int harmonicCount) {
        this.harmonicCount = harmonicCount;
    }
    
    public int getPowerCount() {
        return powerCount;
    }
    
    public void setPowerCount(int powerCount) {
        this.powerCount = powerCount;
    }
    
    public int getPowerNodeCount() {
        return powerNodeCount;
    }
    
    public void setPowerNodeCount(int powerNodeCount) {
        this.powerNodeCount = powerNodeCount;
    }
    
    public int getWindowSize() {
        return windowSize;
    }
    
    public void setWindowSize(int windowSize) {
        this.windowSize = windowSize;
    }
    
    public int getResponsibilityDataCount() {
        return responsibilityDataCount;
    }
    
    public void setResponsibilityDataCount(int responsibilityDataCount) {
        this.responsibilityDataCount = responsibilityDataCount;
    }
    
    public float getHarmonicThreshold() {
        return harmonicThreshold;
    }
    
    public void setHarmonicThreshold(float harmonicThreshold) {
        this.harmonicThreshold = harmonicThreshold;
    }
    
    public float[] getHarmonicData() {
        return harmonicData;
    }
    
    public void setHarmonicData(float[] harmonicData) {
        this.harmonicData = harmonicData;
    }
    
    public float[][] getPowerData() {
        return powerData;
    }
    
    public void setPowerData(float[][] powerData) {
        this.powerData = powerData;
    }
    
    public float[][] getCorrelationData() {
        return correlationData;
    }
    
    public void setCorrelationData(float[][] correlationData) {
        this.correlationData = correlationData;
    }
    
    public float[][] getFkData() {
        return fkData;
    }
    
    public void setFkData(float[][] fkData) {
        this.fkData = fkData;
    }
    
    public float[][] getHkData() {
        return hkData;
    }
    
    public void setHkData(float[][] hkData) {
        this.hkData = hkData;
    }
    
    public float[] getCanonicalCorrelation() {
        return canonicalCorrelation;
    }
    
    public void setCanonicalCorrelation(float[] canonicalCorrelation) {
        this.canonicalCorrelation = canonicalCorrelation;
    }
    
    public float[] getBackgroundCanonicalCorr() {
        return backgroundCanonicalCorr;
    }
    
    public void setBackgroundCanonicalCorr(float[] backgroundCanonicalCorr) {
        this.backgroundCanonicalCorr = backgroundCanonicalCorr;
    }
    
    public CalculationStatus getCalculationStatus() {
        return calculationStatus;
    }
    
    public void setCalculationStatus(CalculationStatus calculationStatus) {
        this.calculationStatus = calculationStatus;
    }
    
    public float[] getSumFKData() {
        return sumFKData;
    }
    
    public void setSumFKData(float[] sumFKData) {
        this.sumFKData = sumFKData;
    }
    
    public float[] getSumHKData() {
        return sumHKData;
    }
    
    public void setSumHKData(float[] sumHKData) {
        this.sumHKData = sumHKData;
    }
}