package de.duehl.swing.ui.dialogs.base;

/*
 * Copyright 2020 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

import de.duehl.swing.logic.Quitter;
import de.duehl.swing.ui.colors.Colorizer;

/**
 * Diese Klasse ist die abstrakte Basis der Dialoge mit JFrame.
 *
 * @version 1.01     2020-02-07
 * @author Christian Dühl
 */

public abstract class NonModalFrameDialogBase extends AbstractDialogBase {

    /** Der Dialog, der dargestellt wird. */
    private final JFrame frame;

    /**
     * Konstruktor für ein gepacktes Fenster ohne fest vorgegebene Dimension.
     *
     * @param dialogTitle
     *            Titel des Dialoges.
     */
    public NonModalFrameDialogBase(String dialogTitle) {
        this(new Point(0, 0), null, dialogTitle, IGNORE_DIMENSION, null);
        ignoreSize();
    }

    /**
     * Konstruktor.
     *
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param dialogDimension
     *            Größe des Dialogs.
     */
    public NonModalFrameDialogBase(String dialogTitle, Dimension dialogDimension) {
        this(new Point(0, 0), null, dialogTitle, dialogDimension, null);
    }

    /**
     * Konstruktor für ein gepacktes Fenster ohne fest vorgegebene Dimension.
     *
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     */
    public NonModalFrameDialogBase(Image programImage, String dialogTitle) {
        this(new Point(0, 0), programImage, dialogTitle, IGNORE_DIMENSION, null);
        ignoreSize();
    }

    /**
     * Konstruktor.
     *
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param dialogDimension
     *            Größe des Dialogs.
     */
    public NonModalFrameDialogBase(Image programImage, String dialogTitle,
            Dimension dialogDimension) {
        this(new Point(0, 0), programImage, dialogTitle, dialogDimension, null);
    }

    /**
     * Konstruktor für ein gepacktes Fenster ohne fest vorgegebene Dimension.
     *
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     */
    public NonModalFrameDialogBase(Point parentLocation, Image programImage, String dialogTitle) {
        this(parentLocation, programImage, dialogTitle, IGNORE_DIMENSION, null);
        ignoreSize();
    }

    /**
     * Konstruktor.
     *
     * @param parentLocation
     *            Die Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Das Icon für das Programm.
     * @param dialogDimension
     *            Größe des Dialogs.
     * @param dialogTitle
     *            Titel des Dialoges.
     */
    public NonModalFrameDialogBase(Point parentLocation, Image programImage, String dialogTitle,
            Dimension dialogDimension) {
        this(parentLocation, programImage, dialogTitle, dialogDimension, null);
    }

    /**
     * Konstruktor für ein gepacktes Fenster ohne fest vorgegebene Dimension.
     *
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param colorizer
     *            Farbverwaltung für die Gui.
     */
    public NonModalFrameDialogBase(Image programImage, String dialogTitle, Colorizer colorizer) {
        this(new Point(0, 0), programImage, dialogTitle, IGNORE_DIMENSION, colorizer);
        ignoreSize();
    }

    /**
     * Konstruktor.
     *
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param dialogDimension
     *            Größe des Dialogs.
     * @param colorizer
     *            Farbverwaltung für die Gui.
     */
    public NonModalFrameDialogBase(Image programImage, String dialogTitle,
            Dimension dialogDimension, Colorizer colorizer) {
        this(new Point(0, 0), programImage, dialogTitle, dialogDimension, colorizer);
    }

    /**
     * Konstruktor für ein gepacktes Fenster ohne fest vorgegebene Dimension.
     *
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param colorizer
     *            Farbverwaltung für die Gui.
     */
    public NonModalFrameDialogBase(Point parentLocation, Image programImage, String dialogTitle,
            Colorizer colorizer) {
        this(parentLocation, programImage, dialogTitle, IGNORE_DIMENSION, colorizer);
        ignoreSize();
    }

    /**
     * Konstruktor.
     *
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Icon für das Programm.
     * @param dialogTitle
     *            Titel des Dialoges.
     * @param dialogDimension
     *            Größe des Dialogs.
     * @param colorizer
     *            Farbverwaltung für die Gui.
     */
    public NonModalFrameDialogBase(Point parentLocation, Image programImage, String dialogTitle,
            Dimension dialogDimension, Colorizer colorizer) {
        super(parentLocation, programImage, dialogDimension, colorizer);

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setTitle(dialogTitle);
        setWindow(frame);
    }

    /** Setzt den Titel des Rahmens neu. */
    protected final void changeTitle(String newTitle) {
        frame.setTitle(newTitle);
        refresh();
    }

    /** Gibt die RootPane des Dialogs zurück. */
    @Override
    public final JRootPane getRootPane() {
        return frame.getRootPane();
    }

    /** Fügt einen Listener zum Beenden des Dialogs über das [x] oben rechts hinzu. */
    @Override
    public void addClosingWindowListener(Quitter quitter) {
        super.addClosingWindowListener(quitter);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    }

    /** Getter für den Titel des Frames. */
    public String getTitle() {
        return frame.getTitle();
    }

    /** Setter für den Titel des Frames. */
    public void setTitle(String title) {
        changeTitle(title);
    }

    /** Getter für den Frame. Möglichst wenig benutzen und lieber deligieren! */
    protected JFrame getFrame() {
        return frame;
    }

    /**
     * Zeigt das Fenster an oder versteckt ihn.
     *
     * @param visible
     *            Gibt an, ob das Fenster angezeigt (true) oder versteckt (false) werden soll.
     */
    @Override
    public void setVisible(boolean visible) {
        /*
         * Anders als in AbstractDialogBase verwenden wir hier SwingUtilities.invokeLater(), da es
         * keinen modalen Dialog gibt, der bei der Verwendung von SwingUtilities.invokeLater() dann
         * nicht nicht mit der weiteren Abarbeitung warten würde.
         */
        SwingUtilities.invokeLater(() -> super.setVisible(visible));
    }

    /** Trägt das Menü ein. */
    public void addMenu(JMenuBar menuBar) {
        frame.setJMenuBar(menuBar);
        frame.validate();
    }

    /** Maximiert das Fenster. */
    public void maximize() {
        SwingUtilities.invokeLater(() -> frame.setExtendedState(JFrame.MAXIMIZED_BOTH));
    }

}
