package de.duehl.swing.ui.elements.progress;

/*
 * Copyright 2024 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.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;

import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import de.duehl.basics.system.SystemTools;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;

/**
 * Diese Klasse stellt einen Dialog zur Anzeige eines Fortschrittsbalken zusammen mit ein paar
 * Angaben zum Fortschritt dar.
 *
 * Es wird erwartet, dass der eigentliche Task in einem eigenen Thread abläuft, um die Gui nicht
 * einfrieren zu lassen, daher wird hier und im verwendeten StandardColoredProgressPanel mit
 * invokeLater() gearbeitet.
 *
 * Eine Demo befindet sich in de.duehl.swing.ui.start.progress.ProgressDialogDemo
 *
 * @version 1.01     2024-11-20
 * @author Christian Dühl
 */

public class ProgressDialog extends ModalDialogBase {

    private static final int DIALOG_WIDTH = 800;

    /** Der Fortschrittsbalken. */
    private final StandardColoredProgressPanel progressPanel;

    /**
     * Konstruktor.
     *
     * @param title
     *            Der Titel des Dialogs.
     * @param parentLocation
     *            Die Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Das Icon für das Programm.
     */
    public ProgressDialog(String title, Point parentLocation, Image programImage) {
        super(parentLocation, programImage, title);
        addClosingWindowListener(() -> {});

        progressPanel = new StandardColoredProgressPanel();
    }

    /**
     * Setter für den Titel über dem Fortschrittsbalken, beispielsweise "Fortschritt des
     * Importierens:".
     */
    public ProgressDialog setProgressTitle(String progressTitle) {
        progressPanel.setProgressTitle(progressTitle);
        return this;
    }

    /** Setter für den Text vor dem Zähler, beispielsweise "Anzahl importierter XML-Dateien: ". */
    public ProgressDialog setCountPrefix(String countPrefix) {
        progressPanel.setCountPrefix(countPrefix);
        return this;
    }

    /** Setter für den Text vor der Stoppuhr, beispielsweise "Laufzeit: ". */
    public ProgressDialog setTimerPrefix(String timerPrefix) {
        progressPanel.setTimerPrefix(timerPrefix);
        return this;
    }

    /**
     * Setter für den Text in der Beschreibung des aktuellen Schrittes, beispielsweise
     * "füge ein: ".
     */
    public ProgressDialog setActualElementPrefix(String actualElementPrefix) {
        progressPanel.setActualElementPrefix(actualElementPrefix);
        return this;
    }

    /**
     * Setter für den Text in der Beschreibung des aktuellen Schrittes vor Start der Ausführung,
     * beispielsweise "noch nichts in die DB geschrieben".
     */
    public ProgressDialog setActualElementPrefixBeforeStart(
            String actualElementPrefixBeforeStart) {
        progressPanel.setActualElementPrefixBeforeStart(actualElementPrefixBeforeStart);
        return this;
    }

    /**
     * Setter für den Text in der Beschreibung des aktuellen Schrittes nach Abarbeitung aller
     * Schritte, beispielsweise "Alle Daten wurden in die Datenbank geschrieben."
     */
    public ProgressDialog setActualElementWhenDone(String actualElementWhenDone) {
        progressPanel.setActualElementWhenDone(actualElementWhenDone);
        return this;
    }

    /** Erzeugt den ProgressPanel. Muss als letztes nach den Settern stehen. */
    public ProgressDialog createProgressPanel() {
        progressPanel.createProgressPanel();
        return this;
    }

    /** Erzeugt die grafische Oberfläche und zeigt den Dialog an. */
    public void createUi() {
        SwingUtilities.invokeLater(() -> createUiInEdt());
    }

    private void createUiInEdt() {
        fillDialog();
        setVisible(true);
    }

    @Override
    protected void populateDialog() {
        add(createDummyLabelForDialogWidth(), BorderLayout.NORTH);
        add(progressPanel.getComponent(), BorderLayout.CENTER);
    }

    private Component createDummyLabelForDialogWidth() {
        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(DIALOG_WIDTH, 0));
        return label;
    }

    /** Initialisiert die Anzahl der auszuführenden Schritte. Erst nach der Erzeugung aufrufen! */
    public void initNumberOfTasksToDo(int numberOfTasksToDo) {
        progressPanel.initNumberOfTasksToDo(numberOfTasksToDo); // nutzt invokeLater
    }

    /** Informiert darüber, dass mit der Arbeit als ganzer begonnen wird. */
    public void startingWithTask() {
        progressPanel.startingWithTask(); // nutzt invokeLater
    }

    /** Informiert darüber, dass ein Task nun ausgeführt wird. */
    public void aboutToExceuteOneTaskSoon(String description) {
        progressPanel.aboutToExceuteOneTaskSoon(description); // nutzt invokeLater
    }

    /** Informiert darüber, dass ein Task ausgeführt wurde. */
    public void oneTaskDone(String description) {
        progressPanel.oneTaskDone(description); // nutzt invokeLater
    }

    /** Hält die Stoppuhr an, falls die noch läuft. */
    public void quit() {
        progressPanel.quit(); // nutzt invokeLater
    }

    /** Beendet den Dialog. */
    public void closeUi() {
        SystemTools.sleep(250); // Damit man das Grün am Ende noch kurz sieht.
        SwingUtilities.invokeLater(() -> closeUiInEdt());
    }

    private void closeUiInEdt() {
        closeDialog();
    }

}
