/* 
 * JGimp - A Java extension for the GIMP
 * Copyright (C) 2002  Georgia Tech Research Corp.
 * Written by Michael Terry, mterry@cc.gatech.edu
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package org.gimp.jgimp.proxy;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;

import org.gimp.jgimp.JGimpBufferOverflowException;
import org.gimp.jgimp.JGimpData;
import org.gimp.jgimp.JGimpDrawable;
import org.gimp.jgimp.JGimpImage;
import org.gimp.jgimp.JGimpInvalidDrawableException;
import org.gimp.jgimp.JGimpInvalidPixelRegionException;
import org.gimp.jgimp.extension.JGimpExtension;
import org.gimp.jgimp.plugin.JGimpPlugIn;

/**
 * JGimpProxy serves as the low-level interface between Java-based code and the
 * GIMP and its PDB (procedural database). This interface enables Java
 * code to:
 * <ul>
 * <li>install Java-based plug-ins (which manipulate a specific image),
 * <li>load extensions (Java programs that continually run and use the GIMP as
 * an image manipulation service),
 * <li>execute procedures in the GIMP, and
 * <li>read and write pixel data.
 * </ul>
 * 
 * In most cases, you should use {@link org.gimp.jgimp.GimpApp} to communicate
 * with the GIMP, because it provides high-level abstractions that make it
 * much easier and more convenient to develop plug-ins and applications using
 * JGimp.
 * <p>
 * Since JGimp is the main conduit between Java code and the GIMP, this is the
 * interface that you need to implement to do things like create a client-server
 * network architecture for remotely controlling the GIMP, or for creating the
 * equivalent of a "render farm." 
 *<p>
 * To write a plug-in or an extension, see {@link org.gimp.jgimp.plugin.JGimpPlugIn}
 * or {@link org.gimp.jgimp.extension.JGimpExtension}, respectively.
 *
 * @see org.gimp.jgimp.plugin.JGimpPlugIn
 * @see org.gimp.jgimp.extension.JGimpExtension
 */
public interface JGimpProxy {

    public final static String JAVAFILES_DIR_KEY  = "jgimp_javafiles_dir";
    public final static String JGIMP_BASE_DIR_KEY = "jgimp_base_dir";

    /**
     * Executes the given GIMP PDB procedure using the given arguments.
     * @return An array of values returned by the procedure. The data returned will
     *         include a status object in the first element of the array which
     *         indicates whether it executed correctly.
     * @throws JGimpProxyException if JGimp cannot successfully call the given
     *         procedure, but <em>not</em> if the procedure executes correctly
     *         and simply returns an error status.
     */
    public JGimpData[] runPDBProcedure(String inProcedureName, JGimpData[] args) throws JGimpProxyException;

    /**
     * Directly copies the pixel region data (all channels and mask data)
     * into the given buffer, making no changes to the data.
     * <p>
     * All byte/channel/mask ordering is dependent upon the GIMP's internal
     * representation of the image data. This method directly copies
     * the pixel data into the given buffer, making it relatively relatively fast.
     * <p>
     * This method is not dependent on the depth of the image (bytes per pixel).
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public void readPixelRegionInNativeByteFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, byte[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;

    /**
     * Directly copies the pixel region data (all channels and mask data)
     * into the given buffer, making no changes to the data; the int
     * buffer is thus consider a raw area of memory, rather than individual
     * integers or pixels.
     * <p>
     * All byte/channel/mask ordering is dependent upon the GIMP's internal
     * representation of the image data. This method directly copies
     * the pixel data into the given buffer, making it relatively fast.
     * <p>
     * The main reason for this method is for 8-bit-per-channel RGBA images
     * since it directly maps a pixel into a single Java int. This data can
     * then be incorporated in a BufferedImage with the appropriate
     * Raster and ColorModel.
     * <p>
     * Note: Because this method directly copies the data into the int array, the pixel
     *       data may not be int-aligned, depending on the drawable's underlying data.
     *       Also, the data will be ordered within the int according to how the bytes
     *       are represented by the GIMP.
     *       For example, given a drawable with only three channels (RGB), each 8 bits,
     *       the first int will contain RGBR, or the three channels of the first pixel,
     *       plus the red channel of the second pixel. Furthermore, the red channel
     *       of the first pixel will be in the higher-order byte of the int on the Intel
     *       platform.
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public void readPixelRegionInNativeIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, int[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;

    /**
     * Creates a buffer to hold the pixel data, and directly copies the pixel
     * region data (all channels and mask data) into the given buffer, making
     * no changes to the data.
     * <p>
     * All byte/channel/mask ordering is dependent upon the GIMP's internal
     * representation of the image data. This method directly copies
     * the pixel data into the given buffer, making it relatively fast.
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public byte[] readPixelRegionInNativeByteFormat(JGimpDrawable inDrawable, int x, int y, int width, int height)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;
    /**
     * Creates a buffer to hold the pixel data, and directly copies the pixel
     * region data (all channels and mask data) into the given buffer, making
     * no changes to the data; the int buffer is thus consider a raw area of
     * memory, rather than individual integers or pixels.
     * <p>
     * All byte/channel/mask ordering is dependent upon the GIMP's internal
     * representation of the image data. This method directly copies
     * the pixel data into the given buffer, making it relatively fast.
     * <p>
     * The main reason for this method is for 8-bit-per-channel RGBA images
     * since it directly maps a pixel into a single Java int. This data can
     * then be incorporated in a BufferedImage with the appropriate
     * Raster and ColorModel.
     * <p>
     * Note: Because this method directly copies the data into the int array, the pixel
     *       data may not be int-aligned, depending on the drawable's underlying data.
     *       Also, the data will be ordered within the int according to how the bytes
     *       are represented by the GIMP.
     *       For example, given a drawable with only three channels (RGB), each 8 bits,
     *       the first int will contain RGBR, or the three channels of the first pixel,
     *       plus the red channel of the second pixel. Furthermore, the red channel
     *       of the first pixel will be in the lower-order byte of the int on the Intel
     *       platform.
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public int[] readPixelRegionInNativeIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;

    /**
     * Reads the pixel region given and transforms the data into a Java-friendly format.
     * <p>
     * The byte ordering is as follows:
     * <ul>
     * <li>ARGB
     * <li>AGGG
     * <li>AIII
     * </ul>
     * where "ARGB" represents an alpha-RGB pixel, AGGG an alpha-grayscale pixel with
     * the single gray channel repeated three times, and AIII an alpha-indexed pixel
     * with the single index repeated three times.
     * Note that the int is always filled up with this data to make it convenient
     * to throw the RGB and grayscale data into a BufferedImage. Furthermore, if the
     * drawable doesn't have an alpha channel, the alpha bits are initialized to 0xFF.
     * To summarize: the alpha channel is always in bits 24-31 of the int,
     * with the red channel in bits 16-23, the green channel in bits 8-15, and the blue,
     * gray, or indexed channels in bits 0-7. The grayscale and indexed byte is repeated
     * in bits 16-23 and 8-15.
     * <p>
     * This method will take longer than the direct copies of pixel regions because of
     * the manipulation of the data to put it in a consistent form. It is also wasteful
     * of memory for image data where each pixel contains less than 32 bits (because
     * each int contains data for at most one pixel).
     * <p>
     * Note: This method is only compatible with images that have at most 32 bits of data per pixel.
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public void readPixelRegionInJavaIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, int[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;

    /**
     * Creates a buffer to hold the pixel data, then reads the pixel region given
     * and transforms the data into a Java-friendly format.
     * <p>
     * The byte ordering is as follows:
     * <ul>
     * <li>ARGB
     * <li>AGGG
     * <li>AIII
     * </ul>
     * where "ARGB" represents an alpha-RGB pixel, AGGG an alpha-grayscale pixel with
     * the single gray channel repeated three times, and AIII an alpha-indexed pixel
     * with the single index repeated three times.
     * Note that the int is always filled up with this data to make it convenient
     * to throw the RGB and grayscale data into a BufferedImage. Furthermore, if the
     * drawable doesn't have an alpha channel, the alpha bits are initialized to 0xFF.
     * To summarize: the alpha channel is always in bits 24-31 of the int,
     * with the red channel in bits 16-23, the green channel in bits 8-15, and the blue,
     * gray, or indexed channels in bits 0-7. The grayscale and indexed byte is repeated
     * in bits 16-23 and 8-15.
     * <p>
     * This method will take longer than the direct copies of pixel regions because of
     * the manipulation of the data to put it in a consistent form. It is also wasteful
     * of memory for image data where each pixel contains less than 32 bits (because
     * each int contains data for at most one pixel).
     * <p>
     * Note: This method is only compatible with images that have at most 32 bits of data per pixel.
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @throws JGimpBufferOverflowException
     */
    public int[] readPixelRegionInJavaIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException, JGimpBufferOverflowException;

    /**
     * Writes the given buffer to the given region of pixels.
     * It is assumed that the data represented in the buffer corresponds
     * to the <em>native</em> byte ordering and format of the given drawable.
     *
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     *
     * @see JGimpProxy#readPixelRegionInNativeByteFormat
     */
    public void writePixelRegionInNativeByteFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, byte[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException;
    /**
     * Writes the given buffer to the given region of pixels.
     * It is assumed that the data represented in the buffer corresponds
     * to the <em>native</em> byte ordering and format of the given drawable.
     * The int buffer passed in is treated like a raw buffer of memory, rather
     * than individual integers or pixels.
     *
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     *
     * @see JGimpProxy#readPixelRegionInNativeIntFormat
     */
    public void writePixelRegionInNativeIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, int[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException;

    /**
     * Writes the given buffer to the given region of pixels.
     * It is assumed that the data represented in the buffer is in the
     * following format:
     * <ul>
     * <li>[A]RGB
     * <li>[A]G
     * <li>[A]I
     * </ul>
     * where "[A]" represents an optional alpha channel, "RGB" is red, green, and blue channels,
     * and "G" and "I" represent grayscale or indexed data, respectively.
     * Note that the alpha channel, if present, is always in bits 24-31 of the int,
     * with the red channel in bits 16-23, the green channel in bits 8-15, and the blue,
     * gray, or indexed channels in bits 0-7.
     * <p>
     * Note: This method is only compatible with images that have at most 32 bits of data per pixel.
     *
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     *
     * @see JGimpProxy#readPixelRegionInNativeIntFormat
     */
    public void writePixelRegionInJavaIntFormat(JGimpDrawable inDrawable, int x, int y, int width, int height, int[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidDrawableException;

    /**
     * Opens the image indicated, using the default GIMP loader for that image type,
     * and returns a reference to that image.
     * This method is intended to be used in client-server applications where
     * the client may wish to open a file that is locally available (i.e., not
     * accessible by the server). It is assumed that the image will be loaded, but not be
     * associated with any particular file, anywhere -- that is, it is considered
     * a new, "untitled" image not associated with a file on any file system.
     *
     * @param image The image to locally load and then open on the server.
     *
     * @throws JGimpProxyException
     * @throws JGimpInvalidPixelRegionException
     * @throws JGimpInvalidDrawableException
     * @return      A reference to the image file just loaded.
     */
    public JGimpImage localLoadImage(java.net.URL image) throws JGimpProxyException, java.io.IOException;

    /**
     * Saves the image to the file indicated to the local file system.
     * This method is intended to be used in client-server applications where
     * the client may wish to save an image to the local file system (rather
     * than the server's file system, which may be unavailable due to security
     * reasons). This method writes the image out locally, but does not make 
     * subsequent calls to the GIMP's PDB "save" functions update this local file
     * (i.e., it is saving a copy locally, but the GIMP knows nothing about this
     * file).
     * @param image         The GIMP image to save.
     * @param drawable      The drawable to save.
     * @param targetFile    The file to save to on the local file system.
     * @param imageType     The format of the image. Callers of this method should consult
     *                      the PDB to identify legal image formats the GIMP can save, and use
     *                      the suffix GIMP uses in its file-X-save functions. For example,
     *                      file-jpeg-save saves in jpeg format; to save as jpeg, the String
     *                      would be "jpeg".
     * @param saveArguments The specific arguments for the specific "save" function, minus
     *                      the image, the drawable, and any file names. For example, to
     *                      save as a Photoshop(tm) PSD file, the file-psd-save function
     *                      lists seven total arguments, the first five of which you do not
     *                      need to supply, since they are automatically filled in by
     *                      this method. The final two arguments, compression and fillorder,
     *                      must be supplied in the saveArguments argument.
     *
     * @throws JGimpProxyException
     * @throws java.io.IOException
     */
    public void localSaveImage(JGimpImage image, JGimpDrawable drawable, java.io.File targetFile, String imageType, JGimpData[] saveArguments)
        throws JGimpProxyException, java.io.IOException;

    /**
     * Currently, a proxy can load either plug-ins or extensions, but not both.
     * This method indicates whether it can install plug-ins or not.
     */
    public boolean canInstallPlugIns();

    /**
     * Currently, a proxy can load either plug-ins or extensions, but not both.
     * This method indicates whether it can load extensions or not.
     */
    public boolean canLoadExtensions();

    /**
     * Installs the plug-in represented by the given URL.
     * The URL can refer to a jarfile, a class file, or a
     * directory. Note that since it is a URL, it does
     * not have to be local, and can refer to a network
     * resource.
     * <p>
     * Specific notes:
     * <ul>
     * <li>If the plug-in is in a jarfile, the jarfile
     *     must have a key-value pair of JGimpPlugIn-Class: classname.
     *     The classname refers to the class name implementing
     *     the JGimpPlugIn interface.
     * <li>If the URL is a class file (e.g., foo.class), then
     *     it is assumed to implement the JGimpPlugIn interface
     * <li>If the URL is a directory, then each file that is either
     *     a jarfile or a class file is attempted to be loaded as in
     *     the above two cases. Sub-directories are <em>not</em> recursed.
     * </ul>
     * @throws JGimpProxyException
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public void installPlugIn(java.net.URL inPlugInURL)
        throws
            JGimpProxyException,
            IOException,
            ClassNotFoundException,
            NoSuchMethodException,
            InstantiationException,
            IllegalAccessException,
            InvocationTargetException;

    /**
     * Installs the given plug-in in the GIMP PDB.
     * This plug-in must be able to either remain resident (so
     * it doesn't need to be re-instantiated), or it must have
     * a constructor that accepts no arguments so that it can
     * be instantiated if it does not remain resident.
     * @throws JGimpProxyException
     */
    public void installPlugIn(JGimpPlugIn inPlugIn) throws JGimpProxyException;

    /**
     * Loads and executes the Java extension in the given URL.
     * Java extensions do not install themselves in the GIMP's
     * menu, but run separately using the GIMP as a service.
     * The URL can refer to a jarfile, a class file, or a
     * directory. Note that since it is a URL, it does
     * not have to be local, and can refer to a network
     * resource.
     * <p>
     * Specific notes:
     * <ul>
     * <li>If the extension is in a jarfile, the jarfile
     *     must have a key-value pair of JGimpExtension-Class: classname.
     *     The classname refers to the class name implementing
     *     the JGimpExtension interface.
     * <li>If the URL is a class file (e.g., foo.class), then
     *     it is assumed to implement the JGimpExtension interface
     * <li>If the URL is a directory, then each file that is either
     *     a jarfile or a class file is attempted to be loaded as in
     *     the above two cases. Sub-directories are <em>not</em> recursed.
     * </ul>
     * @throws JGimpProxyException
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public void loadExtension(URL inExtensionURL)
        throws
            JGimpProxyException,
            IOException,
            ClassNotFoundException,
            NoSuchMethodException,
            InstantiationException,
            IllegalAccessException,
            InvocationTargetException;

    /**
     * Loads and executes the given extension.
     * Java extensions do not install themselves in the GIMP's
     * menu, but run separately using the GIMP as a service.
     * @throws JGimpProxyException
     */
    public void loadExtension(JGimpExtension inExtension) throws JGimpProxyException;

    /**
     * Removes all plug-ins from the GIMP then rescans and reinstalls all Java-based
     * plug-ins.
     */
    public void reloadPlugIns();

    /**
     * Stops any running extensions and removes all extensions installed in the GIMP,
     * then rescans and reinstalls all Java-based extensions.
     */
    public void reloadExtensions();
}
