/*
 * @(#)Drawing.java 5.1
 *
 */

package de.renew.draw.storables.ontology;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.io.File;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Vector;

import de.renew.draw.ui.ontology.DrawingView;
import de.renew.ioontology.ExtensionFileFilter;

/**
 * Drawing is a container for figures.
 * <p>
 * Drawing sends out DrawingChanged events to DrawingChangeListeners
 * whenever a part of its area was invalidated.
 * <hr>
 * <b>Design Patterns</b><P>
 * <img src="images/red-ball-small.gif" width=6 height=6 alt=" o ">
 * <b><a href=../pattlets/sld026.htm>Observer</a></b><br>
 * The Observer pattern is used to decouple the Drawing from its views and
 * to enable multiple views.<hr>
 *
 * @see Figure
 * @see DrawingView
 * @see FigureChangeListener
 */
public interface Drawing extends Storable, FigureChangeListener, Serializable {
    /**
     * Gets the Name of this drawing.
     * @return name
     */
    String getName();

    /**
     * Sets the name of this drawing.
     * @param name new name of drawing
     */
    void setName(String name);

    /**
     * Gets the Filename of this drawing.
     * @return Filename
     */
    File getFilename();

    /**
     * Sets Filename for this Drawing.
     * @param filename new filename
     */
    void setFilename(File filename);

    /**
     * Return true, if a backup has been made since the
     * drawing has been generated.
     * @return boolean, {@code true} if backup has been made
     */
    boolean getBackupStatus();

    /**
     * Inform the drawing that a backup has been generated.
     * @param status boolean, {@code true} if backup generated
     */
    void setBackupStatus(boolean status);

    /**
     * Releases the drawing and its contained figures.
     */
    void release();

    /**
     * Gets a box that contains all figures of this drawing.
     *
     * @see #displayBox
     * @return box that contains all the figures
     */
    Rectangle displayBox();

    /**
     * Returns an enumeration to iterate in
     * Z-order back to front over the figures.
     * @return enumeration to iterate
     */
    FigureEnumeration figures();

    /**
     * Returns an enumeration to iterate in
     * Z-order front to back over the figures.
     * @return enumeration to iterate (reversed)
     */
    FigureEnumeration figuresReverse();

    /**
     * Finds a top level Figure. Use this call for hit detection that
     * should not descend into the figure's children.
     * @param x point on x-axis
     * @param y point on y-axis
     * @return top level figure at given point
     */
    Figure findFigure(int x, int y);

    /**
     * Finds a top level Figure that intersects the given rectangle.
     */
    Figure findFigure(Rectangle r);

    /**
     * Finds a top level Figure that intersects the given rectangle.
     * It supresses the passed
     * in figure. Use this method to ignore a figure
     * that is temporarily inserted into the drawing.
     * @param r rectangle
     * @param without the figure to be ignored during
     *                the find.
     * @return top level figure intersecting with given r
     * excluding temporary figure
     */
    Figure findFigure(Rectangle r, Figure without);

    /**
     * Finds a top level Figure, but suppresses the passed
     * in figure. Use this method to ignore a figure
     * that is temporarily inserted into the drawing.
     *
     * @param x       the x coordinate
     * @param y       the y coordinate
     * @param without the figure to be ignored during
     *                the find.
     * @return top level figure at given point excluding temporary figures
     */
    Figure findFigureWithout(int x, int y, Figure without);

    /**
     * Finds a figure but descends into a figure's
     * children. Use this method to implement <i>click-through</i>
     * hit detection, that is, you want to detect the innermost
     * figure containing the given point.
     * @param x point on x-axis
     * @param y point on y-axis
     * @return innermost figure at given point
     */
    Figure findFigureInside(int x, int y);

    /**
     * Finds a figure but descends into a figure's
     * children. It suppresses the passed
     * in figure. Use this method to ignore a figure
     * that is temporarily inserted into the drawing.
     *
     * @param x       the x coordinate
     * @param y       the y coordinate
     * @param without the figure to be ignored during
     *                the find.
     * @return innermost figure at given point without given temporary figure
     */
    Figure findFigureInsideWithout(int x, int y, Figure without);

    /**
     * Adds a listener for this drawing.
     * @param listener listener to be added
     */
    void addDrawingChangeListener(DrawingChangeListener listener);

    /**
     * Removes a listener from this drawing.
     * @param listener listener to be removed
     */
    void removeDrawingChangeListener(DrawingChangeListener listener);

    /**
     * Gets the listeners of a drawing.
     * @return all listeners of drawing
     */
    Enumeration<DrawingChangeListener> drawingChangeListeners();

    /**
     * Adds a figure and sets its container to refer
     * to this drawing.
     * @param figure figure to be added
     * @return the figure that was inserted.
     */
    Figure add(Figure figure);

    /**
     * Adds a drawing and sets its container to refer
     * to this drawing.
     * @param drawing drawing to be added
     * @return the drawing that was inserted.
     */
    Drawing add(Drawing drawing);

    /**
     * Adds a drawing and sets its container to refer
     * to this drawing.
     * @param drawing drawing to be added
     * @param x point on x-axis
     * @param y point on y-axis
     * @return the drawing that was inserted.
     */
    Drawing add(Drawing drawing, int x, int y);

    /**
     * Adds a vector of figures.
     * @param newFigures new figure to be added
     */
    void addAll(Vector<? extends Figure> newFigures);

    /**
     * Removes the figure from the drawing and releases it.
     * @param figure figure to be removed
     * @return removed figure, null if it was not found
     */
    Figure remove(Figure figure);

    /**
     * Removes a figure from the figure list, but
     * doesn't release it. Use this method to temporarily
     * manipulate a figure outside of the drawing.
     * @param figure figure to be removed
     * @return orphaned figure, null if it was not found
     */
    Figure orphan(Figure figure);

    /**
     * Removes a vector of figures from the figure's list
     * without releasing the figures.
     * @param newFigures vector of figures to be removed
     * @see #orphan
     */
    void orphanAll(Vector<? extends Figure> newFigures);

    /**
     * Removes a vector of figures.
     * @param figures vector of figures to be removed
     * @see #remove
     */
    void removeAll(Vector<? extends Figure> figures);

    /**
     * Removes all figures.
     *
     * @see #remove
     */
    void removeAll();

    /**
     * Replaces a figure in the drawing without
     * removing it from the drawing.
     * @param figure figure to be replaced
     * @param replacement replacement of given figure
     */
    void replace(Figure figure, Figure replacement);

    /**
     * Sends a figure to the back of the drawing.
     * @param figure figure to be sent back
     */
    void sendToBack(Figure figure);

    /**
     * Brings a figure to the front.
     * @param figure figure to bring to front
     */
    void bringToFront(Figure figure);

    /**
     * Draws all the figures back to front.
     * g is of type Graphics2D
     * @param g graphic to be drawn in
     */
    void draw(Graphics g);

    /**
     * Invalidates a rectangle and merges it with the
     * existing damaged area.
     */
    @Override
    void figureInvalidated(FigureChangeEvent e);

    /**
     * Forces an update of the drawing change listeners.
     */
    @Override
    void figureRequestUpdate(FigureChangeEvent e);

    /**
     * Handles a removeFigureRequestRemove request that
     * is passed up the figure container hierarchy.
     *
     * @see FigureChangeListener
     */
    @Override
    void figureRequestRemove(FigureChangeEvent e);

    /**
     * Forces an update of the drawing change listeners.
     */
    void checkDamage();

    /**
     * Acquires the drawing lock.
     */
    void lock();

    /**
     * Releases the drawing lock.
     */
    void unlock();

    /**
     * Returns whether drawing has been modified since last save.
     * @return boolean, {@code true} if has been modified
     */
    boolean isModified();

    /**
     * Notifies the drawing that its modifications have been saved.
     */
    void clearModified();

    /**
     * Tells the current drawing bounds. E.g. the area
     * occupied by all figures.
     * @return current drawing bounds
     **/
    Rectangle getBounds();

    /**
     * Tells the default size for drawings of this type.
     * E.g. the area that should be visible by default
     * when a new drawing is created.
     * @return default size of drawing types
     **/
    Dimension defaultSize();

    /**
     * Determines the type of drawings this drawing should be sorted into.
     * Make it a plural, if possible. Currently, this value is used by
     * {@link CH.ifa.draw.application.WindowsMenu}.
     * @return type of drawing this drawing fits into
     **/
    String getWindowCategory();

    //-------------------------------------------------
    // Methods for file handling determination

    /**
     * Gets the default file filter for this drawing.
     * @return file filter
     */
    ExtensionFileFilter getDefaultFileFilter();

    /**
     * Returns the default file extension used by the ExtensionFileFilter for this drawing.
     * @return ext Extension
     */
    String getDefaultExtension();

    /**
     * Returns the set of file filters that define the supported import file formats.
     * @return set of file filters
     */
    HashSet<ExtensionFileFilter> getImportFileFilters();

    /**
     * Returns the set of file filters that define the supported export file formats.
     * @return set of file filters
     */
    HashSet<ExtensionFileFilter> getExportFileFilters();

    /**
     * Initializes this drawing.
     */
    void init();

    /**
     * Decides whether Drawing is storable.
     * @return true if the Drawing is storable
     */
    boolean isStorable();
}