package de.duehl.swing.version;

/*
 * Copyright 2022 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.Image;
import java.awt.Point;

import javax.swing.SwingUtilities;

import de.duehl.basics.system.SystemTools;
import de.duehl.basics.text.Text;
import de.duehl.basics.text.html.generation.SwingHtmlBuilder;
import de.duehl.basics.version.ChangesBetweenVersionsCutter;
import de.duehl.basics.version.Version;
import de.duehl.swing.ui.text.html.HtmlDialog;
import de.duehl.swing.ui.text.html.HtmlFrame;

/**
 * Diese Klasse zeigt mit Hilfe des ChangesBetweenVersionsCutters die passenden Neuerungen zwischen
 * zwei Versionen aus.
 *
 * @version 1.03     2022-05-02
 * @author Christian Dühl
 */

public class NewsHelper {

    /** Standardmäßige Zeit die vor dem Anzeigen von Neuigkeiten gewartet wird. */
    private static final long DEFAULT_WAIT_TIME = 1200;

    /** Aktuelle Version. */
    private final Version actualVersion;

    /** Version beim letzten Aufruf. */
    private final Version lastVersion;

    /** HTML-Text mit der Beschreibung der Änderungen. */
    private final String changesHtml;

    /** Icon des Programms für den Dialog zum Anzeigen der Änderungen. */
    private final Image programImage;

    /** Position des Programms für den Dialog zum Anzeigen der Änderungen. */
    private final Point location;

    /** Zeit die vor dem Anzeigen von Neuigkeiten gewartet wird. */
    private long waitTime;

    /** Gibt an, ob die Neuigkeiten modal angezeigt werden sollen. */
    private boolean showModal;

    /**
     * Konstruktor.
     *
     * @param actualVersion
     *            Aktuelle Version
     * @param lastVersion
     *            Version beim letzten Aufruf.
     * @param changesHtml
     *            HTML-Text mit der Beschreibung der Änderungen.
     * @param programImage
     *            Icon des Programms für den Dialog zum Anzeigen der Änderungen.
     * @param location
     *            Position des Programms für den Dialog zum Anzeigen der Änderungen.
     */
    public NewsHelper(Version actualVersion, Version lastVersion, String changesHtml,
            Image programImage, Point location) {
        this.actualVersion = actualVersion;
        this.lastVersion = lastVersion;
        this.changesHtml = changesHtml;
        this.programImage = programImage;
        this.location = location;

        waitTime = DEFAULT_WAIT_TIME;
        showModal = true;
    }

    /**
     * Wartet die angegeben Zeit in Millisekunden länger, bevor die Neuigkeiten angezeigt werden.
     */
    public void waitExtraMillis(long millis) {
        waitTime += millis;
    }

    /** Wartet die angegeben Zeit in Sekunden länger, bevor die Neuigkeiten angezeigt werden. */
    public void waitExtraSeconds(int seconds) {
        waitExtraMillis(1000 * seconds);
    }

    /** Setter für die Zeit die vor dem Anzeigen von Neuigkeiten gewartet wird. */
    public void setWaitTimeMillis(long waitTime ) {
        this.waitTime = waitTime;
    }

    /** Legt fest, dass die Neuigkeiten nicht modal angezeigt werden sollen. */
    public void showNonModal() {
        showModal = false;
    }

    /**
     * Prüft ob etwas angezeigt werden muss, schneidet dies passend aus und zeigt es an, wenn
     * nötig.
     */
    public void perhapsShowNews() {
        String newsHtml = cutNews();
        if (!newsHtml.isEmpty()) {
            showNews(newsHtml);
        }
    }

    private String cutNews() {
        if (actualVersion.isNewerThan(lastVersion)) {
            ChangesBetweenVersionsCutter cutter = new ChangesBetweenVersionsCutter(actualVersion,
                    lastVersion, changesHtml);
            return cutter.detectChangesBetweenVersions();
        }
        else {
            return "";
        }
    }

    private void showNews(String newsHtml) {
        String html = createFullHtml(newsHtml);
        new Thread(() -> showNewsAfterAWhile(html)).start();
    }

    private String createFullHtml(String newsHtml) {
        SwingHtmlBuilder html = new SwingHtmlBuilder();
        String header = "Neuerungen seit dem letzten Aufruf";

        html.appendHtml5HeadWithOwnExtendedCss(header, createCssExtension());
        html.appendH1(header);

        html.appendP("Aktuelle Version: " + actualVersion.getVersionAndDate());
        html.appendP("Version beim letzten Start: " + lastVersion.getVersionAndDate());

        html.append(newsHtml);

        html.appendFoot();

        return html.toString();
    }

    private String createCssExtension() {
        return Text.removeLineBreakAtEndIfEndsWith(
                """
                tt, pre, code {
                    color: green;
                    font-size: 1.0625em; /* 17pt;*/
                    font-family: monospace;
                }
                pre {
                    margin-left: 10px;
                    margin-right: 10px;
                }""".indent(4)
                );
    }

    private void showNewsAfterAWhile(String html) {
        if (!showModal) {
            SystemTools.sleep(waitTime);
        }
        showHtmlViaHtml("Neuerungen seit dem letzten Aufruf", html);
    }

    private void showHtmlViaHtml(String title, String html) {
        SwingUtilities.invokeLater(() -> showHtmlViaHtmlInEDT(title, html));
    }

    private void showHtmlViaHtmlInEDT(String title, String html) {
        if (showModal) {
            HtmlDialog dialog = new HtmlDialog(title, programImage, location);
            dialog.setText(html);
            dialog.scrollScrollbarToMinimumLater();
            dialog.setVisible(true);
        }
        else {
            HtmlFrame dialog = new HtmlFrame(title, programImage, location);
            dialog.setText(html);
            dialog.scrollScrollbarToMinimumLater();
            dialog.setVisible(true);
        }
    }

}
