package de.duehl.swing.ui.start;

/*
 * Copyright 2016 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 java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

import de.duehl.swing.logic.Quitter;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.elements.progress.ColoredProgressPanel;
import de.duehl.swing.ui.listener.ClosingWindowListener;
import de.duehl.basics.system.SystemTools;

/**
 * Diese Klasse testet die Klasse ColoredProgressPanel.
 *
 * @version 1.01     2014-06-06
 * @author Christian Dühl
 */

public class ColoredProgressPanelTest implements Quitter {

    /** MainFrame der Anwendung. */
    private JFrame frame;

    /** Button zum Starten des Fortschrittprozesses. */
    private JButton startButton;

    /** Button zum Beenden. */
    private JButton quitButton;

    /** Der Panel mit der Fortschrittsanzeige. */
    private ColoredProgressPanel progressPanel;

    /** Konstruktor. */
    public ColoredProgressPanelTest() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createFrame();
                frame.setVisible(true);
            }
        });
    }

    /** Erstellt den Frame. */
    private void createFrame() {
        GuiTools.setNiceLayoutManager();

        frame = new JFrame("ColoredProgressPanel-Test");
        frame.setLayout(new BorderLayout());

        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new ClosingWindowListener(this));

        frame.add(createCenterPart(), BorderLayout.CENTER);

        frame.setPreferredSize(new Dimension(600, 450));
        frame.setLocation(100, 75);
        frame.pack();
    }

    /** Erzeugt die eigentliche Gui. */
    private Component createCenterPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        //panel.setBorder(BorderFactory.createTitledBorder(""));

        panel.add(createProgressTitle(), BorderLayout.NORTH);
        panel.add(createButtons(), BorderLayout.SOUTH);
        panel.add(createProgressPart(), BorderLayout.CENTER);

        return panel;
    }

    /** Erzeugt den Titel in der Fortschrittsanzeige. */
    private Component createProgressTitle() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder(""));

        JLabel titleLabel = new JLabel("<html>"
                + "<p>Test des ColoredProgressPanel</p>"
                + "</html>");
        GuiTools.biggerFont(titleLabel, 10);
        titleLabel.setHorizontalAlignment(JLabel.CENTER);
        titleLabel.setVerticalAlignment(JLabel.NORTH);
        titleLabel.setBorder(new EmptyBorder(15, 20, 15, 20));
        titleLabel.setForeground(Color.BLUE);

        panel.add(titleLabel, BorderLayout.CENTER);

        return panel;
    }

    /** Erzeugt den Button zum Starten und zum Beenden des Programms. */
    private Component createButtons() {
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BorderLayout());

        JButton runButton = new JButton("Start");
        runButton.setFocusable(false);
        runButton.setEnabled(true);
        runButton.setPreferredSize(new Dimension(100, 40));
        runButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startProgress();
            }
        });
        this.startButton = runButton;
        buttonPanel.add(runButton, BorderLayout.WEST);

        JButton quitButton = new JButton("Beenden");
        quitButton.setFocusable(false);
        quitButton.setEnabled(true);
        quitButton.setPreferredSize(new Dimension(100, 40));
        quitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                quit();
            }
        });
        this.quitButton = quitButton;
        buttonPanel.add(quitButton, BorderLayout.EAST);

        return buttonPanel;
    }

    /** Erzeugt den Fortschritts-Panel. */
    private Component createProgressPart() {
        ColoredProgressPanel panel = new ColoredProgressPanel(
                "Fortschritt des Importierens:",
                "Anzahl importierter XML-Dateien: ", "Laufzeit: ",
                "füge ein: ", "noch nichts in die DB geschrieben",
                "Alle Daten wurden in die Datenbank geschrieben.");
        panel.setBorder(BorderFactory.createTitledBorder(""));
        progressPanel = panel;

        return panel;
    }

    /** Zeigt den Waitcursor an. */
    private void waitcursorOn() {
        frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    }

    /** Zeigt den normalen Cursor an. */
    private void waitcursorOff() {
        frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    /** Startet den Prozess, dessen Fortschritt angezeigt wird. */
    private void startProgress() {
        startButton.setEnabled(false);
        quitButton.setEnabled(false);
        waitcursorOn();
        progressPanel.startStopWatch();
        new Thread(createRunnable()).start();
    }

    /** Erzeugt den Prozess, dessen Fortschritt angezeigt wird. */
    private Runnable createRunnable() {
        return new Runnable() {
            @Override
            public void run() {
                Random random = new Random();
                int max = 10;
                for (int actual = 0; actual < max; ++actual) {
                    String actualElement = "Testobjekt Nummer " + actual;
                    inform(max, actual, actualElement);
                    int seconds = 1 + random.nextInt(5); // 1 ... 5 Sekunden
                    SystemTools.sleep(1000 * seconds);
                }
                inform(max, max, "");
            }
        };
    }

    /** Beendet die Gui. */
    @Override
    public void quit() {
        progressPanel.stopStopWatch();
        frame.setVisible(false);
        frame.dispose();
    }

    /**
     * Wird von den Test-Schritten aufgerufen, wenn es Fortschritte im Prozess
     * gibt.
     *
     * @param subStepsMax
     *            Maximale Anzahl der Teilschritte.
     * @param subStepsDone
     *            Abgearbeitete Anzahl der Teilschritte.
     * @param actualElementDescription
     *            Beschreibung des aktuellen Schritts.
     */
    public void inform(final int subStepsMax, final int subStepsDone,
            final String actualElementDescription) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                internalInform(subStepsMax, subStepsDone,
                        actualElementDescription);
            }
        });
    }

    /**
     * Wird von den Test-Schritten aufgerufen, wenn es Fortschritte im Prozess
     * gibt. Hier nun im Gui-Thread.
     *
     * @param subStepsMax
     *            Maximale Anzahl der Teilschritte.
     * @param subStepsDone
     *            Abgearbeitete Anzahl der Teilschritte.
     * @param actualElementDescription
     *            Beschreibung des aktuellen Schritts.
     */
    private void internalInform(int subStepsMax, int subStepsDone,
            String actualElementDescription) {
        progressPanel.updateProgress(subStepsMax, subStepsDone,
                actualElementDescription);

        if (subStepsDone == subStepsMax) {
            quitButton.setEnabled(true);
            startButton.setEnabled(true);
            waitcursorOff();
            progressPanel.stopStopWatch();
        }
        frame.repaint();
    }

    /** Start des Testprogramms. */
    public static void main(String[] args) {
        new ColoredProgressPanelTest();
    }

}
