/*
 * 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.storage.aggregate;

import java.time.Instant;
import java.time.Duration;
import org.apache.sis.storage.Resource;
import org.apache.sis.coverage.SubspaceNotSpecifiedException;
import org.apache.sis.coverage.grid.GridExtent;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.referencing.privy.ExtentSelector;
import org.apache.sis.util.privy.Strings;


/**
 * Algorithm to apply when more than one grid coverage can be found at the same grid index.
 * A merge may happen if an aggregated coverage is created with {@link CoverageAggregator},
 * and the extent of some source coverages are overlapping in the dimension to aggregate.
 *
 * <h2>Example</h2>
 * A collection of {@link GridCoverage} instances may represent the same phenomenon
 * (for example Sea Surface Temperature) over the same geographic area but at different dates and times.
 * {@link CoverageAggregator} can be used for building a single data cube with a time axis.
 * But if two coverages have overlapping time ranges, and if a user request data in the overlapping region,
 * then the aggregated coverages have more than one source coverages capable to provide the requested data.
 * This enumeration specify how to handle this multiplicity.
 *
 * <h2>Default behavior</h2>
 * If no merge strategy is specified, then the default behavior is to throw
 * {@link SubspaceNotSpecifiedException} when the {@link GridCoverage#render(GridExtent)} method
 * is invoked and more than one source coverage (slice) is found for a specified grid index.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.3
 * @since   1.3
 */
public final class MergeStrategy {
    /**
     * Selects a single slice using criteria based first on temporal extent, then on geographic area.
     * This default instance do not use any duration.
     *
     * @see #selectByTimeThenArea(Duration)
     */
    private static final MergeStrategy SELECT_BY_TIME = new MergeStrategy(null);

    /**
     * Temporal granularity of the time of interest, or {@code null} if none.
     * If non-null, intersections with TOI will be rounded to an integer number of this granularity.
     * This is useful if data are expected at an approximately regular interval
     * and we want to ignore slight variations in the temporal extent declared for each image.
     */
    private final Duration timeGranularity;

    /**
     * Creates a new merge strategy. This constructor is private for now because
     * we have not yet decided a callback API for custom merges.
     */
    private MergeStrategy(final Duration timeGranularity) {
        this.timeGranularity = timeGranularity;
    }

    /**
     * Selects a single slice using criteria based first on temporal extent, then on geographic area.
     * This strategy applies the following rules, in order:
     *
     * <ol>
     *   <li>Slice having largest intersection with the time of interest (TOI) is selected.</li>
     *   <li>If two or more slices have the same intersection with TOI,
     *       then the one with less "overtime" (time outside TOI) is selected.</li>
     *   <li>If two or more slices are considered equal after above criteria,
     *       then the one best centered on the TOI is selected.</li>
     * </ol>
     *
     * <div class="note"><b>Rational:</b>
     * the "smallest time outside" criterion (rule 2) is before "best centered" criterion (rule 3)
     * because of the following scenario: if a user specifies a "time of interest" (TOI) of 1 day
     * and if there are two slices intersecting the TOI, with one slice being a raster of monthly
     * averages the other slice being a raster of daily data, we want the daily data to be selected
     * even if by coincidence the monthly averages is better centered.</div>
     *
     * If the {@code timeGranularity} argument is non-null, then intersections with TOI will be rounded
     * to an integer number of the specified granularity and the last criterion in above list is relaxed.
     * This is useful when data are expected at an approximately regular time interval (for example one remote
     * sensing image per day) and we want to ignore slight variations in the temporal extent declared for each image.
     *
     * <p>If there is no time of interest, or the slices do not declare time range,
     * or some slices are still at equality after application of above criteria,
     * then the selection continues on the basis of geographic criteria:</p>
     *
     * <ol>
     *   <li>Largest intersection with the area of interest (AOI) is selected.</li>
     *   <li>If two or more slices have the same intersection area with AOI, then the one with the less
     *       "irrelevant" material is selected. "Irrelevant" material are area outside the AOI.</li>
     *   <li>If two or more slices are considered equal after above criteria,
     *       the one best centered on the AOI is selected.</li>
     *   <li>If two or more slices are considered equal after above criteria,
     *       then the first of those candidates is selected.</li>
     * </ol>
     *
     * If two slices are still considered equal after all above criteria, then an arbitrary one is selected.
     *
     * <h4>Limitations</h4>
     * Current implementation does not check the vertical dimension.
     * This check may be added in a future version.
     *
     * @param  timeGranularity  the temporal granularity of the Time of Interest (TOI), or {@code null} if none.
     * @return a merge strategy for selecting a slice based on temporal criteria first.
     */
    public static MergeStrategy selectByTimeThenArea(final Duration timeGranularity) {
        return (timeGranularity != null) ? new MergeStrategy(timeGranularity) : SELECT_BY_TIME;
    }

    /**
     * Applies the merge using the strategy represented by this instance.
     * Current implementation does only a slice selection.
     * A future version may allow real merge operations.
     *
     * @param  request     the geographic area and temporal extent requested by user.
     * @param  candidates  grid geometry of all slices that intersect the request. Null elements are ignored.
     * @return index of best slice according the heuristic rules of this {@code MergeStrategy}.
     */
    final Integer apply(final GridGeometry request, final GridGeometry[] candidates) {
        final ExtentSelector<Integer> selector = new ExtentSelector<>(
                request.getGeographicExtent().orElse(null),
                request.getTemporalExtent());

        if (timeGranularity != null) {
            selector.setTimeGranularity(timeGranularity);
            selector.alternateOrdering = true;
        }
        for (int i=0; i < candidates.length; i++) {
            final GridGeometry candidate = candidates[i];
            if (candidate != null) {
                final Instant[] t = candidate.getTemporalExtent();
                final int n = t.length;
                selector.evaluate(candidate.getGeographicExtent().orElse(null),
                                  (n == 0) ? null : t[0],
                                  (n == 0) ? null : t[n-1], i);
            }
        }
        return selector.best();
    }

    /**
     * Returns a resource with same data as specified resource but using this merge strategy.
     * If the given resource is an instance created by {@link CoverageAggregator} and uses a different strategy,
     * then a new resource using this merge strategy is returned. Otherwise the given resource is returned as-is.
     * The returned resource will share the same resources and caches than the given resource.
     *
     * @param  resource  the resource for which to update the merge strategy, or {@code null}.
     * @return resource with updated merge strategy, or {@code null} if the given resource was null.
     */
    public Resource apply(final Resource resource) {
        if (resource instanceof AggregatedResource) {
            return ((AggregatedResource) resource).apply(this);
        }
        return resource;
    }

    /**
     * Returns a string representation of this strategy for debugging purposes.
     *
     * @return string representation of this strategy.
     */
    @Override
    public String toString() {
        return Strings.toString(getClass(), "algo", "selectByTimeThenArea", "timeGranularity", timeGranularity);
    }
}
