package viewer;

import javafx.scene.paint.Color;

/**
 * Histogram of colors, used to generate a list of colors made
 * from several gradients combined, so that the list looks smooth.
 */
record Histogram(double[] breakpoints, Color[] colors) {

    /**
     * Creates a schema of colors.
     * <code>breakpoints</code> and <code>colors</code> must have the same length.
     * Two consecutive indices of <code>colors</code> define a gradient of colors.
     * Those colors will be linearly mapped to the interval defined by the same
     * indices taken in <code>breakpoints</code>
     * For instance, { 0, 0.4, 1.} with { BLACK, RED, WHITE} represents a black
     * to red to white spectrum, where 40% of the point are the black to red
     * gradient, 60% are the red to white gradient.
     *
     * @param breakpoints values from 0 to 1, in increasing order, the first value must be 0 and the last one.
     * @param colors      colors assigned to each breakpoint.
     */
    Histogram {
        assert (breakpoints[0] == 0);
        assert (breakpoints[breakpoints.length - 1] == 1);
        assert (colors.length == breakpoints.length);
    }


    /**
     * Generates a list of colors of given length representing this spectrum.
     *
     * @param howManyPoints the number of colors returned
     * @return a list of colors following the schema defined in the constructor
     */
    Color[] generate(int howManyPoints) {
        Color[] result = new Color[howManyPoints];
        int bpIndex = 0;
        for (int ptIndex = 0; ptIndex < howManyPoints; ptIndex++) {
            double absolute = (double) ptIndex / (double) howManyPoints;
            while (absolute > breakpoints[bpIndex + 1] && bpIndex < breakpoints.length - 1)
                bpIndex++;
            double relative = (absolute - breakpoints[bpIndex]) / (breakpoints[bpIndex + 1] - breakpoints[bpIndex]);
            result[ptIndex] = colors[bpIndex].interpolate(colors[bpIndex + 1], relative);
        }
        return result;
    }

}