class FlowDatasetManager {
    constructor(data) {
        this.activeDatasetIndex = 0;
        this.data = data;

        this.stepLimits = {  // Limits for each step (epoch) of the algorithm
            train: [],
            validation: [],
            generative: []
        };

        function getLimits(stepArray) {
            let currentStepLimits = {min: [], max: []}
            for (let dim = 0; dim < stepArray.length; dim++) {
                let min = Math.min.apply(null, stepArray[dim].map(row => Math.min.apply(Math, row)));
                let max = Math.max.apply(null, stepArray[dim].map(row => Math.max.apply(Math, row)));
                currentStepLimits.min.push(min);
                currentStepLimits.max.push(max);
            }
            return currentStepLimits;
        }

        this.trainDatasets = [];
        for (let i = 0; i < nSteps; i++) {
            this.trainDatasets.push(
                new PathsDataset(
                    this.data.train[i],
                    1.0, 0.7, 0.0, particleSprite,
                    0.0, 0.9, 0.0, particleSprite,
                    particleSize, 0
                )
            )

            // What are the limits for each dimension at this step?
            this.stepLimits.train.push(getLimits(this.data.train[i]));
        }

        this.validationDatasets = [];
        if (this.data.validation.length > 0) {
            for (let i = 0; i < nSteps; i++) {
                this.validationDatasets.push(
                    new PathsDataset(
                        this.data.validation[i],
                        1.0, 0.7, 0.0, particleSprite,
                        0.0, 0.9, 0.0, particleSprite,
                        particleSize, 0
                    )
                )
                this.stepLimits.validation.push(getLimits(this.data.validation[i]));
            }
        }

        this.generativeDatasets = [];
        if (this.data.generative.length > 0) {
            for (let i = 0; i < nSteps; i++) {
                this.generativeDatasets.push(
                    new PathsDataset(
                        this.data.generative[i],
                        1.0, 0.7, 0.0, particleSprite,
                        0.0, 0.9, 0.0, particleSprite,
                        particleSize, 0
                    )
                )
                this.stepLimits.generative.push(getLimits(this.data.generative[i]));
            }
        }
    }

    isTrainActive() {
        return this.activeDatasetIndex === 0;
    }

    isValidationActive() {
        return this.activeDatasetIndex === 1;
    }

    isGenerativeActive() {
        return this.activeDatasetIndex === 2;
    }

    setTrainActive() {
        this.activeDatasetIndex = 0;
    }

    setValidationActive() {
        this.activeDatasetIndex = 1;
    }

    setGenerativeActive() {
        this.activeDatasetIndex = 2;
    }

    limits(step = null) {
        if (this.isTrainActive()) {
            return step === null ? {
                min: this.data.train_minima,
                max: this.data.train_maxima
            } : this.stepLimits.train[step]
        } else if (this.isValidationActive()) {
            return step === null ? {
                min: this.data.validation_minima,
                max: this.data.validation_maxima
            } : this.stepLimits.validation[step]
        } else if (this.isGenerativeActive()) {
            return step === null ? {
                min: this.data.generative_minima,
                max: this.data.generative_maxima
            } : this.stepLimits.generative[step]
        }
    }

    datasets() {
        if (this.isTrainActive()) {
            return this.trainDatasets;
        } else if (this.isValidationActive()) {
            return this.validationDatasets;
        } else if (this.isGenerativeActive()) {
            return this.generativeDatasets;
        }
    }
}