package de.duehl.swing.ui.update.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 javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import de.duehl.basics.text.NumberString;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.components.selections.tools.SelectionsHelper;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;

/**
 * Diese Klasse stellt den Dialog zum Ändern des Updateintervalls dar.
 *
 * @version 1.01     2025-11-13
 * @author Christian Dühl
 */

public class ChangeUpdateIntervalDialog extends ModalDialogBase {

    private static final String UNITY_SECONDS = "Sekunden";
    private static final String UNITY_MINUTES = "Minuten";
    private static final String UNITY_HOURS = "Stunden";
    private static final String UNITY_DAYS = "Tage";


    /** Der Abstand zwischen den Ausführungen des Tasks in Sekunden. */
    private int updateIntervalInSeconds;

    /** Die Komponente des Gui-Elements, das diesen Dialog aufruft. */
    private final Component parentDialog;

    /** Das Gui-Element zum Eingeben des Updateintervalls in der angezeigten Einheit. */
    private final StringSelection updateIntervalSelection;

    /** Das Gui-Element zur Auswahl der Einheit des Updateintervalls. */
    private final JComboBox<String> intervalUnityComboBox;

    /** Gibt an, ob der Dialog erfolgreich mit OK beendet wurde. */
    private boolean applied;

    /**
     * Konstruktor.
     *
     * @param updateIntervalInSeconds
     *            Der bisherige Abstand zwischen den Ausführungen des Tasks in Sekunden.
     * @param parentDialog
     *            Die Komponente des Gui-Elements, das diesen Dialog aufruft.
     */
    public ChangeUpdateIntervalDialog(int updateIntervalInSeconds, Component parentDialog) {
        super("Aktualisierungsintervall festlegen");

        this.updateIntervalInSeconds = updateIntervalInSeconds;
        this.parentDialog = parentDialog;

        updateIntervalSelection = new StringSelection("Updateintervall in der angezeigten Einheit");
        intervalUnityComboBox = new JComboBox<>();

        applied = false;

        fillDialog();
    }

    /** Füllt den Rahmen des Dialoges. */
    @Override
    protected void populateDialog() {
        init();

        add(createDummyWidthPart(), BorderLayout.NORTH);
        add(createMainPart(), BorderLayout.CENTER);
        add(createButtonPart(), BorderLayout.SOUTH);

        pack();
    }

    private void init() {
        initSelections();
        initComboBox();
        fillComboBox();
        initIntervallAndUnitByUpdateIntervalInSeconds();
    }

    private void initSelections() {
        SelectionsHelper.initSelectionAsEditor(updateIntervalSelection);
    }

    private void initComboBox() {
        intervalUnityComboBox.setAlignmentX(JLabel.CENTER);
        intervalUnityComboBox.setAlignmentY(JLabel.CENTER);
        ((JLabel) intervalUnityComboBox.getRenderer()).setHorizontalAlignment(
                SwingConstants.CENTER);
    }

    private void fillComboBox() {
        intervalUnityComboBox.removeAllItems();

        intervalUnityComboBox.addItem(UNITY_SECONDS);
        intervalUnityComboBox.addItem(UNITY_MINUTES);
        intervalUnityComboBox.addItem(UNITY_HOURS);
        intervalUnityComboBox.addItem(UNITY_DAYS);
    }

    private Component createDummyWidthPart() {
        JPanel panel = new JPanel();

        panel.setPreferredSize(new Dimension(500, 0));

        return panel;
    }

    private Component createMainPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        GuiTools.createTitle(panel);

        panel.add(updateIntervalSelection.getPanel(), BorderLayout.CENTER);
        panel.add(intervalUnityComboBox, BorderLayout.EAST);

        return panel;
    }

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

        panel.add(createQuitButton(), BorderLayout.WEST);
        panel.add(createOKButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createQuitButton() {
        JButton button = new JButton();
        button.setText("Beenden");
        //button.setFocusable(false);
        //button.setEnabled(true);
        button.addActionListener(e -> closeDialog());
        return button;
    }

    private Component createOKButton() {
        JButton button = new JButton();
        button.setText("Übernehmen");
        //button.setFocusable(false);
        //button.setEnabled(true);
        button.addActionListener(e -> apply());
        return button;
    }

    private void apply() {
        String newUpdateInterval = updateIntervalSelection.getTrimmedText();

        if (newUpdateInterval.isEmpty()) {
            GuiTools.informUser(parentDialog,
                    "Leeres Aktualisierungsintervall eingegeben!",
                    "Bitte geben Sie eine Zahl ein!");
        }
        else if (NumberString.isDigitSequence(newUpdateInterval)) {
                int updateInterval = Integer.parseInt(newUpdateInterval);
                String unity = (String) intervalUnityComboBox.getSelectedItem();
                updateIntervalInSeconds = calculateSeconds(updateInterval, unity);
                applied = true;
                closeDialog();
        }
        else {
            GuiTools.informUser(parentDialog,
                    "Fehlerhaftes Aktualisierungsintervall eingegeben!",
                    "Bitte geben Sie eine ganze Zahl ein!");
        }
    }

    private int calculateSeconds(int updateInterval, String unity) {
        switch (unity) {
            case UNITY_SECONDS:
                return updateInterval;
            case UNITY_MINUTES:
                return updateInterval * 60;
            case UNITY_HOURS:
                return updateInterval * 60 * 60;
            case UNITY_DAYS:
                return updateInterval * 60 * 60 * 24;
            default:
                throw new RuntimeException("Unbekannte Einheit '" + unity);
        }
    }

    private void initIntervallAndUnitByUpdateIntervalInSeconds() {
        int intervall;
        String unity;

        if (updateIntervalInSeconds < 60) {
            intervall = updateIntervalInSeconds;
            unity = UNITY_SECONDS;
        }
        else if (updateIntervalInSeconds < 60 * 60) {
            intervall = updateIntervalInSeconds / 60;
            unity = UNITY_MINUTES;
        }
        else if (updateIntervalInSeconds < 60 * 60 * 24) {
            intervall = updateIntervalInSeconds / (60 * 60);
            unity = UNITY_HOURS;
        }
        else {
            intervall = updateIntervalInSeconds / (60 * 60 * 24);
            unity = UNITY_DAYS;
        }

        updateIntervalSelection.setText(intervall);
        intervalUnityComboBox.setSelectedItem(unity);
    }

    /** Gibt an, ob der Dialog erfolgreich mit OK beendet wurde. */
    public boolean isApplied() {
        return applied;
    }

    /** Getter für den Abstand zwischen den Ausführungen des Tasks in Sekunden. */
    public int getUpdateIntervalInSeconds() {
        return updateIntervalInSeconds;
    }

}
