package de.duehl.swing.debug.dialog;

/*
 * Copyright 2025 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import de.duehl.basics.system.SystemTools;
import de.duehl.basics.text.NumberString;
import de.duehl.swing.debug.GuiDebugSaver;
import de.duehl.swing.debug.data.DebugMessage;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.NonModalFrameDialogBase;

import static de.duehl.swing.debug.GuiDebug.ALL_CATEGORY;

/**
 * Diese Klasse stellt den Dialog zum Anzeigen der Debugmeldungen.
 *
 * @version 1.01     2025-07-30
 * @author Christian Dühl
 */

public class GuiDebugDialog extends NonModalFrameDialogBase {

    private static final Dimension DILOG_DIMENSION = new Dimension(1800, 1000);
    public static final float DEFAULT_FONT_SIZE = 15f;


    /** Die Kategorien zu denen Meldungen erfolgen. */
    private final List<String> categories;

    /** Die eingegangenen Meldungen nach Kategorie. */
    private final Map<String, List<DebugMessage>> messagesByCategory;

    /** Der Panel mit den Reitern für alle Meldungen und einem zu jeder Kategorie. */
    private final JTabbedPane tabs;

    /** Die Liste mit den Paneln, die in den Reitern angezeigt werden. */
    private final List<CategoryPanel> tabPanels;

    /** Button um die Schriftgröße der Tabelle zu erhöhen. */
    private final JButton increaseFontSizeButton;

    /** Button um die Schriftgröße der Tabelle zu verringern. */
    private final JButton standardFontSizeButton;

    /** Button um die Schriftgröße der Tabelle zu verringern. */
    private final JButton decreaseFontSizeButton;

    /**
     * Konstruktor.
     *
     * @param categories
     *            Die Kategorien zu denen Meldungen erfolgen.
     * @param messagesByCategory
     *            Die eingegangenen Meldungen nach Kategorie.
      */
    public GuiDebugDialog(List<String> categories,
            Map<String, List<DebugMessage>> messagesByCategory, Point parentLocation,
            Image programImage) {
        super(parentLocation, programImage, "Optionen", DILOG_DIMENSION);
        this.categories = categories;
        this.messagesByCategory = messagesByCategory;

        tabs = new JTabbedPane();
        tabPanels = new ArrayList<>();

        increaseFontSizeButton = new JButton();
        standardFontSizeButton = new JButton();
        decreaseFontSizeButton = new JButton();

        init();
        fillDialog();
    }

    private void init() {
        createTabPanelsAndAddToTabs();
        showFirstTab();
    }

    private void createTabPanelsAndAddToTabs() {
        createAllTab();

        for (String category : categories) {
            if (!category.equals(ALL_CATEGORY)) {
                createCategoryTab(category);
            }
        }
    }

    private void createAllTab() {
        List<DebugMessage> messages = messagesByCategory.get(ALL_CATEGORY);
        CategoryPanel panel = new CategoryPanel(messages);
        panel.showCategory();
        panel.crateGui();
        tabPanels.add(panel);
        tabs.add("Alle Meldungen", panel.getPanel());
    }

    private void createCategoryTab(String category) {
        List<DebugMessage> messages = messagesByCategory.get(category);
        CategoryPanel panel = new CategoryPanel(messages);
        panel.crateGui();
        tabPanels.add(panel);
        tabs.add(category, panel.getPanel());
    }

    private void showFirstTab() {
        tabs.setSelectedIndex(0);
    }

    /** Baut die Gui auf. */
    @Override
    protected void populateDialog() {
        initElements();

        add(tabs, BorderLayout.CENTER);
        add(createButtonsPart(), BorderLayout.SOUTH);
    }

    private void initElements() {
        initIncreaseFontSizeButton();
        initStandardFontSizeButton();
        initDecreaseFontSizeButton();
    }

    private void initIncreaseFontSizeButton() {
        increaseFontSizeButton.setText("+");
        increaseFontSizeButton.addActionListener(e -> increaseFontSize());
    }

    private void increaseFontSize() {
        for (CategoryPanel tabPanel : tabPanels) {
            tabPanel.increaseFontSize();
        }
    }

    private void initStandardFontSizeButton() {
        String text = "default size (" + NumberString.twoDecimalPlaces(DEFAULT_FONT_SIZE) + ")";
        standardFontSizeButton.setText(text);
        standardFontSizeButton.addActionListener(e -> standardFontSize());
    }

    private void standardFontSize() {
        for (CategoryPanel tabPanel : tabPanels) {
            tabPanel.standardFontSize();
        }
    }

    private void initDecreaseFontSizeButton() {
        decreaseFontSizeButton.setText("-");
        decreaseFontSizeButton.addActionListener(e -> decreaseFontSize());
    }

    private void decreaseFontSize() {
        for (CategoryPanel tabPanel : tabPanels) {
            tabPanel.decreaseFontSize();
        }
    }

    private Component createButtonsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createLeftButtonsPart(), BorderLayout.WEST);
        panel.add(createOkButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createLeftButtonsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createSaveAllButton(), BorderLayout.WEST);
        panel.add(createSaveByCategoriesButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createSaveAllButton() {
        JButton button = new JButton("<html><center>"
                + "Alle Meldungen in eine"
                + "<br>"
                + "chronologische Datei speichern"
                + "</center></html>");
        button.addActionListener(e -> saveAll());
        return button;
    }

    private void saveAll() {
        String filename = GuiTools.saveFileAs(getWindowAsComponent(),
                SystemTools.getHomeDirectory(), GuiTools.createTextFileFilter());
        if (!filename.isBlank()) {
            saveAll(filename);
        }
    }

    private void saveAll(String filename) {
        GuiDebugSaver saver = new GuiDebugSaver(categories, messagesByCategory);
        saver.saveAll(filename);
    }

    private Component createSaveByCategoriesButton() {
        JButton button = new JButton("<html><center>"
                + "Meldungen nach Kategorien in eine Datei"
                + "<br>"
                + "mit Blöcken pro Kategorie speichern"
                + "</center></html>");
        button.addActionListener(e -> saveByCategories());
        return button;
    }

    private void saveByCategories() {
        String filename = GuiTools.saveFileAs(getWindowAsComponent(),
                SystemTools.getHomeDirectory(), GuiTools.createTextFileFilter());
        if (!filename.isBlank()) {
            saveByCategories(filename);
        }
    }

    private void saveByCategories(String filename) {
        GuiDebugSaver saver = new GuiDebugSaver(categories, messagesByCategory);
        saver.saveByCategories(filename);
    }

    private Component createOkButton() {
        JButton button = new JButton("Beenden");
        button.addActionListener(e -> closeDialog());
        return button;
    }

}
