/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.coverage;

import java.util.List;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.io.Serializable;
import javax.measure.Unit;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.opengis.referencing.operation.MathTransform1D;
import org.apache.sis.referencing.operation.transform.TransferFunction;
import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.internal.feature.Resources;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.iso.Names;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.Debug;


/**
 * Describes the data values in a coverage (the range). For a raster, a sample dimension is a band.
 * A sample dimension can reserve some values for <cite>qualitative</cite> information like  “this
 * is a forest” and some other values for <cite>quantitative</cite> information like a temperature
 * measurements.
 *
 * <div class="note"><b>Example:</b>
 * an image of sea surface temperature (SST) could define the following categories:
 * <table class="sis">
 *   <caption>Example of categories in a sample dimension</caption>
 *   <tr><th>Values range</th> <th>Meaning</th></tr>
 *   <tr><td>[0]</td>          <td>No data</td></tr>
 *   <tr><td>[1]</td>          <td>Cloud</td></tr>
 *   <tr><td>[2]</td>          <td>Land</td></tr>
 *   <tr><td>[10…210]</td>     <td>Temperature to be converted into Celsius degrees through a linear equation</td></tr>
 * </table>
 * In this example, sample values in range [10…210] define a quantitative category, while all others categories are qualitative.
 * </div>
 *
 * <div class="section">Relationship with metadata</div>
 * This class provides the same information than ISO 19115 {@code org.opengis.metadata.content.SampleDimension},
 * but organized in a different way. The use of the same name may seem a risk, but those two types are typically
 * not used in same time.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since 1.0
 * @module
 */
public class SampleDimension implements Serializable {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = -4966135180995819364L;

    /**
     * Identification for this sample dimension. Typically used as a way to perform a band select by
     * using human comprehensible descriptions instead of just numbers. Web Coverage Service (WCS)
     * can use this name in order to perform band sub-setting as directed from a user request.
     *
     * @see #getName()
     */
    private final GenericName name;

    /**
     * The background value, or {@code null} if unspecified. Should be a sample value of
     * a qualitative category in the {@link #categories} list, but this is not mandatory.
     *
     * @see #getBackground()
     */
    private final Number background;

    /**
     * The list of categories making this sample dimension. May be empty but shall never be null.
     */
    private final CategoryList categories;

    /**
     * The transform from samples to real values. May be {@code null} if this sample dimension
     * does not define any transform (which is not the same than defining an identity transform).
     *
     * @see #getTransferFunction()
     */
    private final MathTransform1D transferFunction;

    /**
     * The {@code SampleDimension} that describes values after {@linkplain #getTransferFunction() transfer function}
     * has been applied, or if this {@code SampleDimension} is already converted then the original sample dimension.
     * May be {@code null} if this sample dimension has no transfer function, or {@code this} if the transfer function
     * is the identity function.
     *
     * <p>This field establishes a bidirectional navigation between sample values and real values.
     * This is in contrast with methods named {@link #converted()}, which establish a unidirectional
     * navigation from sample values to real values.</p>
     *
     * @see #converted()
     * @see Category#converse
     * @see CategoryList#converse
     */
    private final SampleDimension converse;

    /**
     * Creates a new sample dimension for values that are already converted to real values.
     * This transfer function is set to identity, which implies that this constructor should
     * be invoked only for sample dimensions having at least one quantitative category.
     *
     * @param  original  the original sample dimension for packed values.
     * @param  bc        category of the background value in original sample dimension, or {@code null}.
     */
    private SampleDimension(final SampleDimension original, final Category bc) {
        converse         = original;
        name             = original.name;
        categories       = original.categories.converse;
        transferFunction = Category.identity();
        if (bc == null) {
            background = null;
        } else {
            background = bc.converse.range.getMinValue();
        }
    }

    /**
     * Creates a sample dimension with the specified name and categories.
     * The sample dimension name is used as a way to perform a band select
     * by using human comprehensible descriptions instead of numbers.
     * The background value is used for filling empty space in map reprojections.
     * The background value (if specified) should be the value of a qualitative category
     * present in the {@code categories} collection, but this is not mandatory.
     *
     * <p>Note that {@link Builder} provides a more convenient way to create sample dimensions.</p>
     *
     * @param name        an identification for the sample dimension.
     * @param background  the background value, or {@code null} if none.
     * @param categories  the list of categories. May be empty if none.
     */
    public SampleDimension(final GenericName name, final Number background, final Collection<? extends Category> categories) {
        ArgumentChecks.ensureNonNull("name", name);
        ArgumentChecks.ensureNonNull("categories", categories);
        final CategoryList list;
        if (categories.isEmpty()) {
            list = CategoryList.EMPTY;
        } else {
            list = CategoryList.create(categories.toArray(new Category[categories.size()]));
        }
        this.name       = name;
        this.background = background;
        this.categories = list;
        if (list.converse.range == null) {                  // Case where there is no quantitative category.
            transferFunction = null;
            converse = null;
        } else if (list == list.converse) {                 // Case where values are already converted.
            transferFunction = Category.identity();
            converse = this;
        } else {
            assert !list.isEmpty();                         // If empty, list.converse.range would have been null.
            transferFunction = list.getTransferFunction();
            converse = new SampleDimension(this, (background != null) ? list.search(background.doubleValue()) : null);
        }
    }

    /**
     * Returns the sample dimension that describes real values. This method establishes a unidirectional navigation
     * from sample values to real values. This is in contrast to {@link #converse}, which establish a bidirectional
     * navigation.
     *
     * @see #forConvertedValues(boolean)
     */
    private SampleDimension converted() {
        // Transfer function shall never be null if 'converse' is non-null.
        return (converse != null && !transferFunction.isIdentity()) ? converse : this;
    }

    /**
     * Returns an identification for this sample dimension. This is typically used as a way to perform a band select
     * by using human comprehensible descriptions instead of just numbers. Web Coverage Service (WCS) can use this name
     * in order to perform band sub-setting as directed from a user request.
     *
     * @return an identification of this sample dimension.
     *
     * @see org.opengis.metadata.content.RangeDimension#getSequenceIdentifier()
     */
    public GenericName getName() {
        return name;
    }

    /**
     * Returns all categories in this sample dimension. Note that a {@link Category} object may apply to an arbitrary range
     * of sample values. Consequently, the first element in this collection may not be directly related to the sample value
     * {@code 0}.
     *
     * @return the list of categories in this sample dimension, or an empty list if none.
     */
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public List<Category> getCategories() {
        return categories;                      // Safe to return because immutable.
    }

    /**
     * Returns the background value. If this sample dimensions has quantitative categories, then the background
     * value should be one of the value returned by {@link #getNoDataValues()}. However this is not mandatory.
     *
     * @return the background value, typically (but not necessarily) one of {@link #getNoDataValues()}.
     */
    public Optional<Number> getBackground() {
        return Optional.ofNullable(background);
    }

    /**
     * Returns the values to indicate "no data" for this sample dimension.
     * If the sample dimension describes {@linkplain #forConvertedValues(boolean) converted values},
     * then the "no data values" are NaN values.
     *
     * @return the values to indicate no data values for this sample dimension, or an empty set if none.
     * @throws IllegalStateException if this method can not expand the range of no data values, for example
     *         because some ranges contain an infinite amount of values.
     */
    public Set<Number> getNoDataValues() {
        if (converse != null) {             // Null if SampleDimension does not contain at least one quantitative category.
            final boolean isConverted = transferFunction.isIdentity();
            final NumberRange<?>[] ranges = new NumberRange<?>[categories.size()];
            Class<? extends Number> widestClass = Byte.class;
            int count = 0;
            for (final Category category : categories) {
                final Category converted = category.converted();
                if ((isConverted || category != converted) && converted.isConvertedQualitative()) {
                    final NumberRange<?> range = category.range;
                    if (!range.isBounded()) {
                        throw new IllegalStateException(Resources.format(Resources.Keys.CanNotEnumerateValuesInRange_1, range));
                    }
                    widestClass = Numbers.widestClass(widestClass, range.getElementType());
                    ranges[count++] = range;
                }
            }
            if (count != 0) {
                final Set<Number> noDataValues = new TreeSet<>(SampleDimension::compare);
                for (int i=0; i<count; i++) {
                    final NumberRange<?> range = ranges[i];
                    final Number minimum = range.getMinValue();
                    final Number maximum = range.getMaxValue();
                    if (range.isMinIncluded()) noDataValues.add(Numbers.cast(minimum, widestClass));
                    if (range.isMaxIncluded()) noDataValues.add(Numbers.cast(maximum, widestClass));
                    if (Numbers.isInteger(range.getElementType())) {
                        long value = minimum.longValue() + 1;       // If value was inclusive, then it has already been added to the set.
                        long stop  = maximum.longValue() - 1;
                        while (value <= stop) {
                            noDataValues.add(Numbers.wrap(value, widestClass));
                        }
                    } else if (!minimum.equals(maximum)) {
                        throw new IllegalStateException(Resources.format(Resources.Keys.CanNotEnumerateValuesInRange_1, range));
                    }
                }
                return noDataValues;
            }
        }
        return Collections.emptySet();
    }

    /**
     * Compares as {@code double} values. This method is similar to {@link Double#compare(double,double)}
     * except that it also orders NaN values from raw bit patterns. Reminder: NaN values are sorted last.
     */
    private static int compare(final Number n1, final Number n2) {
        return Category.compare(n1.doubleValue(), n2.doubleValue());
    }

    /**
     * Returns the range of values occurring in this sample dimension. The range delimits sample values that
     * can be converted into real values using the {@linkplain #getTransferFunction() transfer function}.
     * If that function is {@linkplain MathTransform1D#isIdentity() identity}, then the values are already
     * real values and the range may be an instance of {@link MeasurementRange}
     * (i.e. a number range with units of measurement).
     *
     * @return the range of sample values in this sample dimension.
     */
    public Optional<NumberRange<?>> getSampleRange() {
        return Optional.ofNullable(categories.range);
    }

    /**
     * Returns the range of values after conversions by the transfer function.
     * This range is absent if there is no transfer function.
     *
     * @return the range of values after conversion by the transfer function.
     *
     * @see #getUnits()
     */
    public Optional<MeasurementRange<?>> getMeasurementRange() {
        if (converse == null) {
            return Optional.empty();
        }
        // A ClassCastException below would be a bug in our constructors.
        return Optional.ofNullable((MeasurementRange<?>) converted().categories.range);
    }

    /**
     * Returns the <cite>transfer function</cite> from sample values to real values.
     * This method returns a transform expecting sample values as input and computing real values as output.
     * The output units of measurement is given by {@link #getUnits()}.
     *
     * <p>This transform takes care of converting all "{@linkplain #getNoDataValues() no data values}" into {@code NaN} values.
     * The <code>transferFunction.{@linkplain MathTransform1D#inverse() inverse()}</code> transform is capable to differentiate
     * those {@code NaN} values and get back the original sample value.</p>
     *
     * @return the <cite>transfer function</cite> from sample to real values. May be absent if this sample dimension
     *         does not define any transform (which is not the same that defining an identity transform).
     */
    public Optional<MathTransform1D> getTransferFunction() {
        return Optional.ofNullable(transferFunction);
    }

    /**
     * Returns the scale factor and offset of the transfer function.
     * The formula returned by this method does <strong>not</strong> take
     * "{@linkplain #getNoDataValues() no data values}" in account.
     * For a more generic transfer function, see {@link #getTransferFunction()}.
     *
     * @return a description of the part of the transfer function working on real numbers.
     * @throws IllegalStateException if the transfer function can not be simplified in a form representable
     *         by {@link TransferFunction}.
     */
    public Optional<TransferFunction> getTransferFunctionFormula() {
        MathTransform1D tr = null;
        for (final Category category : categories) {
            final Optional<MathTransform1D> c = category.getTransferFunction();
            if (c.isPresent()) {
                if (tr == null) {
                    tr = c.get();
                } else if (!tr.equals(c.get())) {
                    throw new IllegalStateException(Resources.format(Resources.Keys.CanNotSimplifyTransferFunction_1));
                }
            }
        }
        if (tr == null) {
            return Optional.empty();
        }
        final TransferFunction f = new TransferFunction();
        try {
            f.setTransform(tr);
        } catch (IllegalArgumentException e) {
            throw new IllegalStateException(Resources.format(Resources.Keys.CanNotSimplifyTransferFunction_1, e));
        }
        return Optional.of(f);
    }

    /**
     * Returns the units of measurement for this sample dimension.
     * This unit applies to values obtained after the {@linkplain #getTransferFunction() transfer function}.
     * May be absent if not applicable.
     *
     * @return the units of measurement.
     * @throws IllegalStateException if this sample dimension use different units.
     *
     * @see #getMeasurementRange()
     */
    public Optional<Unit<?>> getUnits() {
        Unit<?> unit = null;
        for (final Category category : converted().categories) {
            final NumberRange<?> r = category.range;
            if (r instanceof MeasurementRange<?>) {
                final Unit<?> c = ((MeasurementRange<?>) r).unit();
                if (c != null) {
                    if (unit == null) {
                        unit = c;
                    } else if (!unit.equals(c)) {
                        throw new IllegalStateException();
                    }
                }
            }
        }
        return Optional.ofNullable(unit);
    }

    /**
     * Returns a sample dimension that describes real values or sample values, depending if {@code converted} is {@code true}
     * or {@code false} respectively.  If there is no {@linkplain #getTransferFunction() transfer function}, then this method
     * returns {@code this}.
     *
     * @param  converted  {@code true} for a sample dimension describing converted values,
     *                    or {@code false} for a sample dimension describing packed values.
     * @return a sample dimension describing converted or packed values, depending on {@code converted} argument value.
     *         May be {@code this} but never {@code null}.
     *
     * @see org.apache.sis.coverage.grid.GridCoverage#forConvertedValues(boolean)
     */
    public SampleDimension forConvertedValues(final boolean converted) {
        // Transfer function shall never be null if 'converse' is non-null.
        if (converse != null && transferFunction.isIdentity() != converted) {
            return converse;
        }
        return this;
    }

    /**
     * Returns a hash value for this sample dimension.
     */
    @Override
    public int hashCode() {
        return categories.hashCode() + 31*name.hashCode();
    }

    /**
     * Compares the specified object with this sample dimension for equality.
     *
     * @param  object  the object to compare with.
     * @return {@code true} if the given object is equals to this sample dimension.
     */
    @Override
    public boolean equals(final Object object) {
        if (object == this) {
            return true;
        }
        if (object instanceof SampleDimension) {
            final SampleDimension that = (SampleDimension) object;
            return name.equals(that.name) && Objects.equals(background, that.background) && categories.equals(that.categories);
        }
        return false;
    }

    /**
     * Returns a string representation of this sample dimension.
     * This string is for debugging purpose only and may change in future version.
     *
     * @return a string representation of this sample dimension for debugging purpose.
     */
    @Override
    public String toString() {
        return new SampleRangeFormat(Locale.getDefault()).write(new SampleDimension[] {this});
    }

    /**
     * Returns a string representation of the given sample dimensions.
     * This string is for debugging purpose only and may change in future version.
     *
     * @param  locale      the locale to use for formatting texts.
     * @param  dimensions  the sample dimensions to format.
     * @return a string representation of the given sample dimensions for debugging purpose.
     */
    @Debug
    public static String toString(final Locale locale, SampleDimension... dimensions) {
        ArgumentChecks.ensureNonNull("dimensions", dimensions);
        return new SampleRangeFormat(locale).write(dimensions);
    }




    /**
     * A mutable builder for creating an immutable {@link SampleDimension}.
     * The following properties can be set:
     *
     * <ul>
     *   <li>An optional name for the {@code SampleDimension}.</li>
     *   <li>A single optional category for the background value.</li>
     *   <li>An arbitrary amount of <cite>qualitative</cite> categories.</li>
     *   <li>An arbitrary amount of <cite>quantitative</cite> categories.</li>
     * </ul>
     *
     * A <cite>qualitative category</cite> is a range of sample values associated to a label (not numbers).
     * For example 0 = cloud, 1 = sea, 2 = land, <i>etc</i>.
     * A <cite>quantitative category</cite> is a range of sample values associated to numbers with units of measurement.
     * For example 10 = 1.0°C, 11 = 1.1°C, 12 = 1.2°C, <i>etc</i>.
     * Those three kinds of category are created by the following methods:
     *
     * <ul>
     *   <li>{@link #setBackground(CharSequence, Number)}</li>
     *   <li>{@link #addQualitative(CharSequence, NumberRange)}</li>
     *   <li>{@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}</li>
     * </ul>
     *
     * All other {@code addQualitative(…)} and {@code addQuantitative(…)} methods are convenience methods delegating
     * to above-cited methods. Qualitative and quantitative categories can be mixed in the same {@link SampleDimension},
     * provided that their ranges do not overlap.
     * After properties have been set, the sample dimension is created by invoking {@link #build()}.
     *
     * @author  Martin Desruisseaux (IRD, Geomatys)
     * @version 1.0
     * @since   1.0
     * @module
     */
    public static class Builder {
        /**
         * Identification for this sample dimension.
         */
        private GenericName dimensionName;

        /**
         * The categories for the sample dimension to create.
         * This list is modified by the following methods:
         *
         * <ul>
         *   <li>{@link #setBackground(CharSequence, Number)}</li>
         *   <li>{@link #addQualitative(CharSequence, NumberRange)}</li>
         *   <li>{@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}</li>
         *   <li>{@code categories().remove(int)}</li>
         *   <li>{@link #clear()}</li>
         * </ul>
         *
         * @see #categories()
         */
        private Category[] categories;

        /**
         * Number of valid elements in {@link #categories}.
         */
        private int count;

        /**
         * The ordinal NaN values used for this sample dimension.
         * The {@link Category} constructor uses this set for avoiding collisions.
         */
        private final ToNaN toNaN;

        /**
         * Creates an initially empty builder for a sample dimension.
         * Callers shall invoke at least one {@code addFoo(…)} method before {@link #build()}.
         */
        public Builder() {
            categories = new Category[10];
            toNaN      = new ToNaN();
        }

        /**
         * Sets an identification of the sample dimension.
         * This is the value to be returned by {@link SampleDimension#getName()}.
         * If this method is invoked more than once, then the last specified name prevails
         * (previous sample dimension names are discarded).
         *
         * @param  name  identification of the sample dimension.
         * @return {@code this}, for method call chaining.
         */
        public Builder setName(final GenericName name) {
            dimensionName = name;
            return this;
        }

        /**
         * Sets an identification of the sample dimension as a character sequence.
         * This is a convenience method for creating a {@link GenericName} from the given characters.
         *
         * @param  name  identification of the sample dimension.
         * @return {@code this}, for method call chaining.
         */
        public Builder setName(final CharSequence name) {
            dimensionName = createLocalName(name);
            return this;
        }

        /**
         * Sets an identification of the sample dimension as a band number.
         * This method should be used only when no more descriptive name is available.
         *
         * @param  band  sequence identifier of the sample dimension to create.
         * @return {@code this}, for method call chaining.
         */
        public Builder setName(final int band) {
            dimensionName = Names.createMemberName(null, null, band);
            return this;
        }

        /**
         * A common place where are created local names from character string.
         * For making easier to revisit if we want to add a namespace.
         */
        private static GenericName createLocalName(final CharSequence name) {
            return Names.createLocalName(null, null, name);
        }

        /**
         * Creates a range for the given minimum and maximum values. We use the static factory methods instead
         * than the {@link NumberRange} constructor for sharing existing range instances. This is also a way
         * to ensure that the number type is one of the primitive wrappers.
         *
         * <p>This method is invoked for qualitative categories only. For that reason, it accepts NaN values.</p>
         */
        private static NumberRange<?> range(final Class<?> type, Number minimum, Number maximum) {
            switch (Numbers.getEnumConstant(type)) {
                case Numbers.BYTE:    return NumberRange.create(minimum.byteValue(),  true, maximum.byteValue(),   true);
                case Numbers.SHORT:   return NumberRange.create(minimum.shortValue(), true, maximum.shortValue(),  true);
                case Numbers.INTEGER: return NumberRange.create(minimum.intValue(),   true, maximum.intValue(),    true);
                case Numbers.LONG:    return NumberRange.create(minimum.longValue(),  true, maximum.longValue(),   true);
                case Numbers.FLOAT: {
                    final float min = minimum.floatValue();
                    final float max = maximum.floatValue();
                    if (!Float.isNaN(min) || !Float.isNaN(max)) {       // Let 'create' throws an exception if only one value is NaN.
                        return NumberRange.create(min, true, max, true);
                    }
                    if (minimum.getClass() != Float.class) minimum = min;
                    if (maximum.getClass() != Float.class) maximum = max;
                    break;
                }
                default: {
                    final double min = minimum.doubleValue();
                    final double max = maximum.doubleValue();
                    if (!Double.isNaN(min) || !Double.isNaN(max)) {     // Let 'create' throws an exception if only one value is NaN.
                        return NumberRange.create(min, true, max, true);
                    }
                    if (minimum.getClass() != Double.class) minimum = min;
                    if (maximum.getClass() != Double.class) maximum = max;
                    break;
                }
            }
            @SuppressWarnings({"unchecked", "rawtypes"})
            final NumberRange<?> samples = new NumberRange(type, minimum, true, maximum, true);
            return samples;
        }

        /**
         * Adds a qualitative category and marks that category as the background value.
         * This is the value to be returned by {@link SampleDimension#getBackground()}.
         * If this method is invoked more than once, then the last specified value prevails
         * (previous values become ordinary qualitative categories).
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "fill value" name.
         * @param  sample  the background value.
         * @return {@code this}, for method call chaining.
         */
        public Builder setBackground(CharSequence name, Number sample) {
            ArgumentChecks.ensureNonNull("sample", sample);
            if (name == null) {
                name = Vocabulary.formatInternational(Vocabulary.Keys.FillValue);
            }
            final NumberRange<?> samples = range(sample.getClass(), sample, sample);
            // Use of 'getMinValue()' below shall be consistent with ToNaN.remove(Category).
            toNaN.background = samples.getMinValue();
            add(new Category(name, samples, null, null, toNaN));
            return this;
        }

        /**
         * Adds a qualitative category for samples of the given boolean value.
         * The {@code true} value is represented by 1 and the {@code false} value is represented by 0.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as a boolean.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final boolean sample) {
            final byte value = sample ? (byte) 1 : 0;
            return addQualitative(name, NumberRange.create(value, true, value, true));
        }

        /**
         * Adds a qualitative category for samples of the given tiny (8 bits) integer value.
         * The argument is treated as a signed integer ({@value Byte#MIN_VALUE} to {@value Byte#MAX_VALUE}).
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as an integer.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final byte sample) {
            return addQualitative(name, NumberRange.create(sample, true, sample, true));
        }

        /**
         * Adds a qualitative category for samples of the given short (16 bits) integer value.
         * The argument is treated as a signed integer ({@value Short#MIN_VALUE} to {@value Short#MAX_VALUE}).
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as an integer.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final short sample) {
            return addQualitative(name, NumberRange.create(sample, true, sample, true));
        }

        /**
         * Adds a qualitative category for samples of the given integer value.
         * The argument is treated as a signed integer ({@value Integer#MIN_VALUE} to {@value Integer#MAX_VALUE}).
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as an integer.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final int sample) {
            return addQualitative(name, NumberRange.create(sample, true, sample, true));
        }

        /**
         * Adds a qualitative category for samples of the given floating-point value.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as a real number.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final float sample) {
            return addQualitative(name, NumberRange.create(sample, true, sample, true));
        }

        /**
         * Adds a qualitative category for samples of the given double precision floating-point value.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object,
         *                 or {@code null} for a default "no data" name.
         * @param  sample  the sample value as a real number.
         * @return {@code this}, for method call chaining.
         */
        public Builder addQualitative(final CharSequence name, final double sample) {
            return addQualitative(name, NumberRange.create(sample, true, sample, true));
        }

        /**
         * Adds a qualitative category for samples in the given range of values.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div>
         *
         * @param  name     the category name as a {@link String} or {@link InternationalString} object,
         *                  or {@code null} for a default "no data" name.
         * @param  minimum  the minimum sample value, inclusive.
         * @param  maximum  the maximum sample value, inclusive.
         * @return {@code this}, for method call chaining.
         * @throws IllegalArgumentException if the range is empty.
         */
        public Builder addQualitative(final CharSequence name, final Number minimum, final Number maximum) {
            return addQualitative(name, range(Numbers.widestClass(minimum, maximum), minimum, maximum));
        }

        /**
         * Adds a qualitative category for all samples in the specified range of values.
         * This is the most generic method for adding a qualitative category.
         * All other {@code addQualitative(name, …)} methods are convenience methods delegating their work to this method.
         *
         * @param  name     the category name as a {@link String} or {@link InternationalString} object,
         *                  or {@code null} for a default "no data" name.
         * @param  samples  the minimum and maximum sample values in the category.
         * @return {@code this}, for method call chaining.
         * @throws IllegalArgumentException if the given range is empty.
         */
        public Builder addQualitative(CharSequence name, final NumberRange<?> samples) {
            if (name == null) {
                name = Vocabulary.formatInternational(Vocabulary.Keys.Nodata);
            }
            add(new Category(name, samples, null, null, toNaN));
            return this;
        }

        /**
         * Constructs a quantitative category mapping samples to real values in the specified range.
         * Sample values in the {@code samples} range will be mapped to real values in the {@code converted} range
         * through a linear equation of the form:
         *
         * <blockquote><var>measure</var> = <var>sample</var> × <var>scale</var> + <var>offset</var></blockquote>
         *
         * where <var>scale</var> and <var>offset</var> coefficients are computed from the ranges supplied in arguments.
         * The units of measurement will be taken from the {@code converted} range if it is an instance of {@link MeasurementRange}.
         *
         * <p><b>Warning:</b> this method is provided for convenience when the scale and offset factors are not explicitly specified.
         * If those factor are available, then the other {@code addQuantitative(name, samples, …)} methods are more reliable.</p>
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}.</div>
         *
         * @param  name        the category name as a {@link String} or {@link InternationalString} object.
         * @param  samples     the minimum and maximum sample values in the category. Element class is usually
         *                     {@link Integer}, but {@link Float} and {@link Double} values are accepted as well.
         * @param  converted   the range of real values for this category, as an instance of {@link MeasurementRange}
         *                     if those values are associated to an unit of measurement.
         * @return {@code this}, for method call chaining.
         * @throws ClassCastException if the range element class is not a {@link Number} subclass.
         * @throws IllegalArgumentException if the range is invalid.
         */
        public Builder addQuantitative(final CharSequence name, final NumberRange<?> samples, final NumberRange<?> converted) {
            ArgumentChecks.ensureNonNull("samples", samples);
            ArgumentChecks.ensureNonNull("converted", converted);
            /*
             * We need to perform calculation using the same "included versus excluded" characteristics for sample and converted
             * values. We pickup the characteristics of the range using floating point values because it is easier to adjust the
             * bounds of the range using integer values (we just add or subtract 1 for integers, while the amount to add to real
             * numbers is not so clear). If both ranges use floating point values, arbitrarily adjust the converted values.
             */
            final boolean isMinIncluded, isMaxIncluded;
            if (Numbers.isInteger(samples.getElementType())) {
                isMinIncluded = converted.isMinIncluded();                         // This is the usual case.
                isMaxIncluded = converted.isMaxIncluded();
            } else {
                isMinIncluded = samples.isMinIncluded();                            // Less common case.
                isMaxIncluded = samples.isMaxIncluded();
            }
            final double minValue  = converted.getMinDouble(isMinIncluded);
            final double Δvalue    = converted.getMaxDouble(isMaxIncluded) - minValue;
            final double minSample =   samples.getMinDouble(isMinIncluded);
            final double Δsample   =   samples.getMaxDouble(isMaxIncluded) - minSample;
            final double scale     = Δvalue / Δsample;
            final TransferFunction transferFunction = new TransferFunction();
            transferFunction.setScale(scale);
            transferFunction.setOffset(minValue - scale * minSample);               // TODO: use Math.fma with JDK9.
            return addQuantitative(name, samples, transferFunction.getTransform(),
                    (converted instanceof MeasurementRange<?>) ? ((MeasurementRange<?>) converted).unit() : null);
        }

        /**
         * Adds a quantitative category for values ranging from {@code minimum} to {@code maximum} inclusive
         * in the given units of measurement. The transfer function is set to identity.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}.</div>
         *
         * @param  name     the category name as a {@link String} or {@link InternationalString} object.
         * @param  minimum  the minimum value (inclusive) in the given units.
         * @param  maximum  the maximum value (inclusive) in the given units.
         * @param  units    the units of measurement.
         * @return {@code this}, for method call chaining.
         * @throws IllegalArgumentException if a value is NaN or if {@code minimum} is greater than {@code maximum}.
         */
        public Builder addQuantitative(CharSequence name, float minimum, float maximum, Unit<?> units) {
            return addQuantitative(name, MeasurementRange.create(minimum, true, maximum, true, units), Category.identity(), units);
        }

        /**
         * Adds a quantitative category for values ranging from {@code minimum} to {@code maximum} inclusive
         * in the given units of measurement. The transfer function is set to identity.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}.</div>
         *
         * @param  name     the category name as a {@link String} or {@link InternationalString} object.
         * @param  minimum  the minimum value (inclusive) in the given units.
         * @param  maximum  the maximum value (inclusive) in the given units.
         * @param  units    the units of measurement.
         * @return {@code this}, for method call chaining.
         * @throws IllegalArgumentException if a value is NaN or if {@code minimum} is greater than {@code maximum}.
         */
        public Builder addQuantitative(CharSequence name, double minimum, double maximum, Unit<?> units) {
            return addQuantitative(name, MeasurementRange.create(minimum, true, maximum, true, units), Category.identity(), units);
        }

        /**
         * Adds a quantitative category for sample values ranging from {@code lower} inclusive to {@code upper} exclusive.
         * Sample values are converted into real values using the following linear equation:
         *
         * <blockquote><var>measure</var> = <var>sample</var> × <var>scale</var> + <var>offset</var></blockquote>
         *
         * Results of above conversion are measurements in the units specified by the {@code units} argument.
         *
         * <div class="note"><b>Implementation note:</b>
         * this convenience method delegates to {@link #addQuantitative(CharSequence, NumberRange, MathTransform1D, Unit)}.</div>
         *
         * @param  name    the category name as a {@link String} or {@link InternationalString} object.
         * @param  lower   the lower sample value, inclusive.
         * @param  upper   the upper sample value, exclusive.
         * @param  scale   the scale value which is multiplied to sample values for the category. Must be different than zero.
         * @param  offset  the offset value to add to sample values for this category.
         * @param  units   the units of measurement of values after conversion by the scale factor and offset.
         * @return {@code this}, for method call chaining.
         * @throws IllegalArgumentException if {@code lower} is not smaller than {@code upper},
         *         or if {@code scale} or {@code offset} are not real numbers, or if {@code scale} is zero.
         */
        public Builder addQuantitative(CharSequence name, int lower, int upper, double scale, double offset, Unit<?> units) {
            final TransferFunction transferFunction = new TransferFunction();
            transferFunction.setScale(scale);
            transferFunction.setOffset(offset);
            return addQuantitative(name, NumberRange.create(lower, true, upper, false), transferFunction.getTransform(), units);
        }

        /**
         * Constructs a quantitative category for all samples in the specified range of values.
         * Sample values (usually integers) will be converted into real values
         * (usually floating-point numbers) through the {@code toUnits} transform.
         * Results of that conversion are measurements in the units specified by the {@code units} argument.
         *
         * <p>This is the most generic method for adding a quantitative category.
         * All other {@code addQuantitative(name, …)} methods are convenience methods delegating their work to this method.</p>
         *
         * @param  name     the category name as a {@link String} or {@link InternationalString} object.
         * @param  samples  the minimum and maximum sample values in the category. Element class is usually
         *                  {@link Integer}, but {@link Float} and {@link Double} types are accepted as well.
         * @param  toUnits  the transfer function from sample values to real values in the specified units.
         * @param  units    the units of measurement of values after conversion by the transfer function.
         * @return {@code this}, for method call chaining.
         * @throws ClassCastException if the range element class is not a {@link Number} subclass.
         * @throws IllegalArgumentException if the range is invalid.
         *
         * @see TransferFunction
         */
        public Builder addQuantitative(CharSequence name, NumberRange<?> samples, MathTransform1D toUnits, Unit<?> units) {
            ArgumentChecks.ensureNonNull("toUnits", toUnits);
            add(new Category(name, samples, toUnits, units, toNaN));
            return this;
        }

        /**
         * Adds the given category to the list. This method is not public because the category
         * should have been created with {@link #toNaN} passed in argument to its constructor.
         */
        private void add(final Category category) {
            if (count == categories.length) {
                categories = Arrays.copyOf(categories, count * 2);
            }
            categories[count++] = category;
        }

        /**
         * Returns the list of categories added so far. The returned list does not support the
         * {@link List#add(Object) add} operation, but supports the {@link List#remove(int) remove} operation.
         *
         * @return the current category list, read-only except for the {@code remove} operation.
         */
        public List<Category> categories() {
            return new AbstractList<Category>() {
                /** Returns the number of categories in this list. */
                @Override public int size() {
                    return count;
                }

                /** Returns the category at the given index. */
                @Override public Category get(int i) {
                    ArgumentChecks.ensureValidIndex(count, i);
                    return categories[i];
                }

                /** Removes the category at the given index. */
                @Override public Category remove(int i) {
                    ArgumentChecks.ensureValidIndex(count, i);
                    final Category c = categories[i];
                    System.arraycopy(categories, i+1, categories, i, --count - i);
                    categories[count] = null;
                    toNaN.remove(c);
                    return c;
                }
            };
        }

        /**
         * Creates a new sample with the properties defined to this builder.
         *
         * @return the sample dimension.
         */
        public SampleDimension build() {
            GenericName name = dimensionName;
defName:    if (name == null) {
                for (int i = 0; i < count; i++) {
                    if (categories[i].isQuantitative()) {
                        name = createLocalName(categories[i].name);
                        break defName;
                    }
                }
                name = createLocalName(Vocabulary.formatInternational(Vocabulary.Keys.Untitled));
            }
            return new SampleDimension(name, toNaN.background, UnmodifiableArrayList.wrap(categories, 0, count));
        }

        /**
         * Reset this builder to the same state than after construction.
         * The sample dimension name, background values and all categories are discarded.
         * This method can be invoked when the same builder is reused for creating more than one sample dimension.
         */
        public void clear() {
            dimensionName = null;
            count = 0;
            Arrays.fill(categories, null);
            toNaN.clear();
        }
    }
}
