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

/*
 * Copyright 2021 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.Color;
import java.awt.Component;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.border.EmptyBorder;

import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.elements.watch.StopWatchLabel;
import de.duehl.swing.ui.layout.VerticalLayout;
import de.duehl.basics.io.FileHelper;
import de.duehl.basics.text.NumberString;

/**
 * Diese Klasse stellt einen Fortschrittsbalken zusammen mit ein paar Angaben zum Fortschritt dar.
 *
 * Mit der Verwendung von StandardColoredProgressPanel macht man sich das Leben leichter!
 *
 * @version 1.01     2021-03-17
 * @author Christian Dühl
 */

public class ColoredProgressPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private static final Color AT_WORK_COLOR = new Color(220, 142, 0);
    private static final Color DONE_COLOR = new Color(100, 200, 100);

    /** Titel über dem Fortschrittsbalken, beispielsweise "Fortschritt des Importierens:". */
    private String progressTitle;

    /** Text vor dem Zähler, beispielsweise "Anzahl importierter XML-Dateien: ". */
    private String countPrefix;

    /** Text vor der Stoppuhr, beispielsweise "Laufzeit: ". */
    private String timerPrefix;

    /** Text in der Beschreibung des aktuellen Schrittes, beispielsweise "füge ein: ". */
    private String actualElementPrefix;

    /**
     * Text in der Beschreibung des aktuellen Schrittes vor Start der Ausführung, beispielsweise
     * "noch nichts in die DB geschrieben".
     */
    private String actualElementPrefixBeforeStart;

    /**
     * Text in der Beschreibung des aktuellen Schrittes nach Abarbeitung aller Schritte,
     * beispielsweise "Alle Daten wurden in die Datenbank geschrieben."
     */
    private String actualElementWhenDone;

    /** Der eigentliche Fortschrittsbalken. */
    private JProgressBar progressBar;

    /** Zeigt an, was in diesem Augenblick getan wird. */
    private JLabel infoLabel;

    /** Zeigt die bisherige Laufzeit an. */
    private StopWatchLabel stopWatchLabel;

    /**
     * Zeigt an, wieviele Schritte von denen, die insgesamt zu erledigen sind, schon abgearbeitet
     * wurden.
     */
    private JLabel countLabel;

    /** Gibt an, ob die Stoppuhr angezeigt werden soll. */
    private boolean showWatch;

    /**
     * Konstruktor.
     *
     * @param progressTitle
     *            Titel über dem Fortschrittsbalken, beispielsweise "Fortschritt des
     *            Importierens:".
     * @param countPrefix
     *            Text vor dem Zähler, beispielsweise "Anzahl importierter XML-Dateien: ".
     * @param timerPrefix
     *            Text vor der Stoppuhr, beispielsweise "Laufzeit: ".
     * @param actualElementPrefix
     *            Text in der Beschreibung des aktuellen Schrittes, beispielsweise "füge ein: ".
     * @param actualElementPrefixBeforeStart
     *            Text in der Beschreibung des aktuellen Schrittes vor Start der Ausführung,
     *            beispielsweise "noch nichts in die DB geschrieben".
     * @param actualElementWhenDone
     *            Text in der Beschreibung des aktuellen Schrittes nach abarbeitung aller Schritte,
     *            beispielsweise "Alle Daten wurden in die Datenbank geschrieben."
     */
    public ColoredProgressPanel(String progressTitle, String countPrefix, String timerPrefix,
            String actualElementPrefix, String actualElementPrefixBeforeStart,
            String actualElementWhenDone) {
        this(progressTitle, countPrefix, timerPrefix, actualElementPrefix,
                actualElementPrefixBeforeStart, actualElementWhenDone, true);
    }

    /**
     * Konstruktor.
     *
     * @param progressTitle
     *            Titel über dem Fortschrittsbalken, beispielsweise "Fortschritt des
     *            Importierens:".
     * @param countPrefix
     *            Text vor dem Zähler, beispielsweise "Anzahl importierter XML-Dateien: ".
     * @param timerPrefix
     *            Text vor der Stoppuhr, beispielsweise "Laufzeit: ".
     * @param actualElementPrefix
     *            Text in der Beschreibung des aktuellen Schrittes, beispielsweise "füge ein: ".
     * @param actualElementPrefixBeforeStart
     *            Text in der Beschreibung des aktuellen Schrittes vor Start der Ausführung,
     *            beispielsweise "noch nichts in die DB geschrieben".
     * @param actualElementWhenDone
     *            Text in der Beschreibung des aktuellen Schrittes nach abarbeitung aller Schritte,
     *            beispielsweise "Alle Daten wurden in die Datenbank geschrieben."
     * @param showWatch
     *            Gibt an, ob die Stoppuhr angezeigt werden soll.
     */
    public ColoredProgressPanel(String progressTitle, String countPrefix, String timerPrefix,
            String actualElementPrefix, String actualElementPrefixBeforeStart,
            String actualElementWhenDone, boolean showWatch) {
        this.progressTitle = progressTitle;
        this.countPrefix = countPrefix;
        this.timerPrefix = timerPrefix;
        this.actualElementPrefix = actualElementPrefix;
        this.actualElementPrefixBeforeStart = actualElementPrefixBeforeStart;
        this.actualElementWhenDone = actualElementWhenDone;
        this.showWatch = showWatch;

        setLayout(new BorderLayout());
        //setBorder(BorderFactory.createTitledBorder(""));

        add(createProgressBar(), BorderLayout.NORTH);
        add(createProgressbarInformations(), BorderLayout.CENTER);
    }

    /** Erzeugt den Fortschrittbalken. */
    private Component createProgressBar() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        //panel.setBorder(BorderFactory.createTitledBorder(""));
        panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));

        JLabel progressLabel = new JLabel(progressTitle);
        GuiTools.biggerFont(progressLabel, 5);
        panel.add(progressLabel, BorderLayout.NORTH);

        JProgressBar progressBar = new ColoredProgressBar(0, 100);
        progressBar.setValue(0);
        progressBar.setStringPainted(false);
        //progressBar.setForeground(NOT_YET_COLOR);
        this.progressBar = progressBar;
        panel.add(progressBar, BorderLayout.CENTER);

        return panel;
    }

    /** Erzeugt die Anzeigen unter dem Fortschrittbalken. */
    private Component createProgressbarInformations() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(0, VerticalLayout.BOTH));
        //panel.setBorder(BorderFactory.createTitledBorder(""));

        JLabel infoLabel = new JLabel(actualElementPrefixBeforeStart);
        //GuiTools.biggerFont(infoLabel, -2);
        //infoLabel.setForeground(NOT_YET_COLOR);
        GuiTools.biggerFont(infoLabel, 5);
        panel.add(infoLabel);
        this.infoLabel = infoLabel;

        countLabel = new JLabel(countPrefix + 0);
        //countLabel.setForeground(NOT_YET_COLOR);
        GuiTools.biggerFont(countLabel, 5);
        panel.add(countLabel);
        countLabel.setBorder(new EmptyBorder(15,  0,  15,  0));

        if (showWatch) {
            stopWatchLabel = new StopWatchLabel(timerPrefix, "");
            //stopWatchLabel.setForeground(NOT_YET_COLOR);
            GuiTools.biggerFont(stopWatchLabel, 5);
            panel.add(stopWatchLabel);
        }
        else {
            stopWatchLabel = null;
        }

        return panel;
    }

    /**
     * Informiert über Fortschritte im Prozess.
     *
     * @param subStepsMax
     *            Maximale Anzahl der Teilschritte.
     * @param subStepsDone
     *            Abgearbeitete Anzahl der Teilschritte.
     * @param actualElementDescription
     *            Beschreibung des aktuellen Schritts.
     */
    public void updateProgress(int subStepsMax, int subStepsDone, String actualElementDescription) {
        progressBar.setValue(subStepsDone);
        countLabel.setText(countPrefix + NumberString.taupu(subStepsDone) + " / "
                + NumberString.taupu(subStepsMax));

        if (!actualElementDescription.isEmpty()) {
            infoLabel.setText(actualElementPrefix
                    + FileHelper.getBareName(actualElementDescription));
        }

        if (subStepsDone == 0) {
            progressBar.setForeground(AT_WORK_COLOR);
            progressBar.setMaximum(subStepsMax);
            progressBar.setStringPainted(true);
        }
        else if (subStepsDone == subStepsMax) {
            progressBar.setForeground(DONE_COLOR);
            infoLabel.setText(actualElementWhenDone);
            if (showWatch) {
                stopWatchLabel.stop();
            }
        }

        repaint();
    }

    /** Hält die Stoppuhr an. Sonst läuft der Thread des StopWatchLabels weiter! */
    public void stopStopWatch() {
        if (showWatch) {
            stopWatchLabel.stop();
        }
    }

    /**
     * Liest die Zeit auf der Stoppuhr ab. Wenn die Stoppuhr mit stop() angehalten wurde, wird die
     * angehaltene Zeit zurückgegeben, ansonsten die Zeit, die vom Start bis jetzt vergangen ist.
     *
     * Die Zeit wird in einem von Menschen lesbarem Format erzeugt.
     */
    public String getRuntime() {
        if (showWatch) {
            return stopWatchLabel.getTime();
        }
        else {
            return "not available";
        }
    }

    /**
     * Startet die Stoppuhr neu. wenn vorher andere Dinge laufen, ist sonst
     * schon Zeit vergangen.
     */
    public void startStopWatch() {
        if (showWatch) {
            stopWatchLabel.start();
        }
    }

}
