import { PeakDetectorSimple } from './PeakDetection';
import { MovingAverage} from './MovingAverage';
import { List } from 'immutable';


export default class DataAnalysis {

    constructor() {
        this._resetCache(null, 0);
    }

    analyze(analysisParameters, sessionId, allMeasurements) {
        const cacheValid = (
            this.sessionId === sessionId &&
            this.analyzedUpToIdx <= allMeasurements.size &&
            this.analysisParameters === analysisParameters);

        let newData = null;

        if (cacheValid) {
            newData = allMeasurements.slice(this.analyzedUpToIdx);
        }
        else {
            this._resetCache(analysisParameters, sessionId);
            newData = allMeasurements;
            console.log("cache reset");
        }
        const allMeasurementsSize = newData.size ? newData.size : newData.length;
        const newDataArr = (typeof newData.toArray ==="function") ? newData.toArray() : newData;
        
        // active time
        const newAverages = this.movingAverage.addVector(newDataArr);
        this.activeMeasurements += newAverages.reduce((n, val) => {
            return n + ((val >= analysisParameters.activeTimeThreshold) ? 1 : 0);
        }, 0);

        // peaks 
        const newPeaks = this.peakDetectorSimple.addVector(newDataArr);
        this.allPeaks = this.allPeaks.concat(List(newPeaks));

        // aggregated sum/max
        this.aggregatedMomentum = newData.reduce((sum, x) => sum + x, this.aggregatedMomentum);
        this.peakMax = newData.reduce((running, x) => Math.max(x, running), this.peakMax);

        // windowed
        const windowNumDataPoints = analysisParameters.windowSizeInSecs * analysisParameters.numMeasurementsPerSec;
        const windowed = allMeasurements.slice(-windowNumDataPoints);
        const peakMaxWindow = windowed.reduce((running, x) => Math.max(x, running), 0);
        const momentumWindow = windowed.reduce((sum, x) => sum + x, 0);
        

        this.analyzedUpToIdx = allMeasurementsSize;
        return {
            peaks: this.allPeaks,
            totalTime: allMeasurementsSize / analysisParameters.numMeasurementsPerSec,
            activeTime: this.activeMeasurements / analysisParameters.numMeasurementsPerSec,

            totalMomentum: this.aggregatedMomentum,
            peakMax: this.peakMax,

            momentumWindow: momentumWindow,
            peakMaxWindow: peakMaxWindow,
        };
    }
    
    _resetCache(analysisParameters, sessionId) {
        this.movingAverage = analysisParameters ? new MovingAverage(analysisParameters.movingAverageWindowSize) : null;
        this.activeMeasurements = 0;

        this.peakDetectorSimple = analysisParameters ? new PeakDetectorSimple(analysisParameters.peakDetectorSimpleThreshold) : null;
        this.allPeaks = List();

        this.aggregatedMomentum = 0;
        this.peakMax = 0;

        this.sessionId = sessionId;
        this.analyzedUpToIdx = 0;
        this.analysisParameters = analysisParameters;
    }
};