package de.renew.draw.ui.api;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;

import de.renew.draw.storables.ontology.Drawing;
import de.renew.draw.storables.ontology.DrawingListener;
import de.renew.draw.ui.api.services.EditorService;
import de.renew.draw.ui.impl.services.EditorServiceImpl;
import de.renew.draw.ui.ontology.DrawingEditor;
import de.renew.draw.ui.ontology.DrawingView;

/**
 * Service class for the Editor.
 *
 * @author Percy Hohberg
 */
public final class EditorApi {

    private static EditorService _service;

    // The static initialization that creates the service object
    static {
        _service = new EditorServiceImpl();
    }

    /**
     * Loads drawings from the given URL and opens them in the editor.
     * @param url Url of the drawing that will be opened
     */
    public static void loadAndOpenDrawings(URL url) {
        _service.loadAndOpenDrawings(url);
    }

    // As this class only provides static functionality,
    // no instances are allowed to be created.
    private EditorApi() {}

    /**
     * Loads drawings from the given stream with the given name.
     * @param stream given input stream
     * @param fileName name of the file that will be opened in the editor
     */
    public static void loadAndOpenDrawings(InputStream stream, String fileName) throws IOException {
        _service.loadAndOpenDrawings(stream, fileName);
    }

    /**
     * Opens the drawing from the given file. If it is not in the drawing list, it
     * will be loaded.
     * @param file that will be opened or loaded
     */
    public static void openOrLoadDrawing(File file) {
        _service.openOrLoadDrawing(file);
    }

    /**
     * Checks whether the drawing has some accumulated damage
     * and informs all views about the required update,
     * if necessary.
     */
    public static void checkDamage() {
        _service.checkDamage();
    }

    /**
     * Repair the damaged area of the current view.
     */
    public static void repairDamage() {
        _service.repairDamage();
    }

    /**
     * Informs the editor that a tool has done its interaction.
     * This method can be used to switch back to the default tool.
     */
    public static void toolDone() {
        _service.toolDone();
    }

    /**
     * Adds the specified mouse listener to receive mouse events from the current view.
     * If the listener is null, no exception is thrown and no action is performed.
     * @param mouseListener Listener that is added
     */
    public static void addMouseListener(MouseListener mouseListener) {
        _service.addMouseListener(mouseListener);
    }

    /**
     * Removes the specified mouse listener to receive mouse events from the current view.
     * If the listener is null, no exception is thrown and no action is performed.
     * @param mouseListener Listener that is removed
     */
    public static void removeMouseListener(MouseListener mouseListener) {
        _service.removeMouseListener(mouseListener);
    }

    /**
     * Get the current drawing editor. If no DrawPlugin or no GUI is available, the NullDrawingEditor is returned.
     * <p>
     *     If possible, an interaction with the Editor should not be implemented by working with the result of this method,
     *     but by calling the other methods provided by this API.
     * </p>
     *
     * @return the current drawing editor
     */
    public static DrawingEditor getCurrentEditor() {
        return _service.getCurrentEditor();
    }

    /**
     * Gets the NullDrawingEditor.
     * <p>
     *     If the goal is accessing the NullDrawingEditor when no DrawPlugin or GUI is available, please use {@link #getCurrentEditor()} instead.
     * </p>
     *
     * @return the null drawing editor
     */
    public static DrawingEditor getNullDrawingEditor() {
        return _service.getNullDrawingEditor();
    }

    /**
     * Gets the NullDrawingView.
     *
     * @return the null drawing view
     */
    public static DrawingView getNullDrawingView() {
        return _service.getNullDrawingView();
    }

    /**
     * Get the current drawing.
     *
     * @return the current drawing
     */
    public static Drawing getCurrentDrawing() {
        return _service.getCurrentDrawing();
    }

    /**
     * Get all currently open drawings of the application
     *
     * @return all drawing that are opened
     */
    public static Enumeration<Drawing> getCurrentDrawings() {
        return _service.getCurrentDrawings();
    }

    /**
     * Opens the given drawing in the editor.
     * The view frame is created with default position and size.
     *
     * @param drawing the {@code Drawing} to open
     * @return the drawing, which will be opened
     **/
    public static Drawing openDrawing(Drawing drawing) {
        return _service.openDrawing(drawing);
    }

    /**
     * Opens the given drawing in the editor at its specified position with specified dimension.
     *
     * @param drawing the drawing that will be opened
     * @param point the position where the drawing will be opened
     * @param dimension the dimension of the drawing
     */
    public static void openDrawing(Drawing drawing, Point point, Dimension dimension) {
        _service.openDrawing(drawing, point, dimension);
    }

    /**
     * Closes the given drawing.
     *
     * @param drawing the drawing to close
     */
    public static void closeDrawing(Drawing drawing) {
        _service.closeDrawing(drawing);
    }

    /**
     * Adds a drawing listener to the list of drawing listeners.
     *
     * @param listener the listener to add
     */
    public static void addDrawingListener(DrawingListener listener) {
        _service.addDrawingListener(listener);
    }

    /**
     * Removes drawing listener from the list of drawing listeners.
     *
     * @param listener the listener to remove
     */
    public static void removeDrawingListener(DrawingListener listener) {
        _service.removeDrawingListener(listener);
    }
}
