package uk.ac.starlink.topcat.plot2;

import java.util.Map;
import uk.ac.starlink.ttools.plot.Range;
import uk.ac.starlink.ttools.plot2.Navigator;
import uk.ac.starlink.ttools.plot2.PlotLayer;
import uk.ac.starlink.ttools.plot2.ReportMap;
import uk.ac.starlink.ttools.plot2.Surface;

/**
 * Object which manages information about one zone of a multi-zone plot.
 *
 * @author   Mark Taylor
 * @since    18 Aug 2023
 */
public interface ZoneController<P,A> extends Configger {

    /**
     * Sets fixed data position coordinate ranges.
     * If these are not set then they may need to be calculated by
     * examining the data to work out the plot aspect.
     * Setting them to null ensures a re-range if required next time.
     *
     * @param  ranges  fixed data position coordinate ranges, or null to clear
     */
    void setRanges( Range[] ranges );

    /**
     * Returns the current fixed data coordinate ranges.
     * If not known, null is returned.
     *
     * @return   fixed data position coordinate ranges, or null if not known
     */
    Range[] getRanges();

    /**
     * Sets the plot aspect which defines the view on the data.
     * If not set, it may have to be worked out from config and range inputs.
     *
     * @param  aspect  fixed aspect, or null to clear
     */
    void setAspect( A aspect );

    /**
     * Returns the plot aspect to use for setting up the plot surface.
     * If not known, null is returned.
     *
     * @return  fixed aspect, or null if none set
     */
    A getAspect();

    /**
     * Clears aspect constraints explicitly set by the user.
     */
    void clearAspect();

    /**
     * Configures this controller for a given set of plot layers.
     * This may trigger a resetting of the aspect and ranges, generally
     * if the new plot is sufficiently different from most recent one.
     *
     * <p>This isn't perfect, since it only allows to clear the range or not.
     * Sometimes you might want finer control, e.g. to clear the
     * range in one dimension and retain it in others.  It may be
     * possible to fit that into the updateState API, but it
     * would require more work.
     *
     * @param  profile   surface profile
     * @param  layers   layers which will be plotted
     * @param  axisLock  whether re-ranging is inhibited;
     *                   normally, if true axes will not be reset by this
     *                   method, but the implementation can override that
     *                   if it needs to
     */
    void updateState( P profile, PlotLayer[] layers, boolean axisLock );

    /**
     * Accepts report information generated by plotting layers.
     * Null map values are permitted, with the same meaning as an empty map.
     *
     * <p>The default implementation does nothing, but subclasses may
     * override it to enquire about plot results.
     *
     * @param   reports  per-layer plot reports for layers generated
     *                   by the most recent plot
     */
    void submitReports( Map<LayerId,ReportMap> reports );

    /**
     * Accepts information about the latest plotting surface to be plotted
     * by the panel associated with this controller.
     * This method is intended for passing information back to this controller,
     * which does not otherwise have access to the asynchronously constructed
     * Surface object it has configured,
     * it is not an instruction to adjust the current state.
     *
     * <p>The default implementation does nothing, but subclasses may
     * override it to acquire information about plot state.
     *
     * @param  surface  latest plotting surface.
     */
    void setLatestSurface( Surface surface );

    /**
     * Returns the navigator specified by this control.
     *
     * @return  current navigator
     */
    Navigator<A> getNavigator();
}
