package org.eclipse.jetty.server;

import java.io.IOException;
import java.util.Map;


/**
 * <p>
 * This class represents a call-back mechanism that will notify implementations
 * as HTTP body parameters becomes available to be read without blocking.
 * </p>
 * <p>
 * A typical usage pattern is:
 * <pre>
 *    class MyParameterListener implements ParameterListener
 *    {
 *      public void onParameterAvailable(Stream stream) throws IOException
 *      {
 *        while(stream.isReady())
 *          process(stream.getParameter());
 *      }
 *    }
 *  </pre>
 */
public interface ParameterListener
{
    /**
     * When an instance of the <code>ParameterListener</code> is registered with a {@link ServletInputStream},
     * this method will be invoked by the container the first time when it is possible
     * to read a Parameter. Subsequently the container will invoke this method if and only
     * if {@link Stream#isReady()} method has been called and has returned <code>false</code>.
     *
     * @throws IOException if an I/O related error has occurred during processing
     */
    void onParameterAvailable(ParameterListener.Stream stream) throws IOException;

    /**
     * Invoked when all data for the current request has been read.
     *
     * @throws IOException if an I/O related error has occurred during processing
     */

    public default void onAllDataRead() throws IOException {};

    /**
     * Invoked when an error occurs processing the request.
     */
    public default void onError(Throwable t) {};
    
    public interface Stream
    {
        /**
         * @return True if a Parameter is available to be returned from getParameter();
         */
        boolean isReady();
        
        /**
         * @return A Parameter that has been read from the request body.  The Parameter will be fully
         * constituted either in memory or as a file, so that any calls on the {@link Parameter#getInputStream()}
         * will not block on the remote connection.
         * @throws IllegalStateException if {@link #isReady()} has not been call or has been
         * called and returned false.
         */
        Map.Entry<String, String> getParameter();
    }
}