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

/*
 * Copyright 2023 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.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;

import de.duehl.basics.text.NumberString;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;

/**
 * Diese Klasse öffnet einen kleinen Dialog zum Wählen einer Größe aus fest vorgegebenen Werten.
 *
 * @version 1.02     2023-06-29
 * @author Christian Dühl
 */

public class SizeChooser extends ModalDialogBase {

    /** Wert für "kein Wert ausgewählt", etwa bei Abbruch oder Eingabe eines falschen Wertes. */
    public static final int NO_VALUE_SELECTED = -1;

    /** Anzahl Zeilen in der Anordnung der Zahlen. */
    private final int rows;

    /** Anzahl Spalten in der Anordnung der Zahlen. */
    private final int columns;

    /** Menge der erlaubten auswählbaren Werte. */
    private final List<Integer> possibleSizes;

    /** Hier ausgewählte neue Größe. */
    private int size;

    /** Gibt an, ob auch andere Größen zulässig sind. */
    private boolean differentSizesAreOk;

    /** Liste der Buttons. */
    private final List<JButton> buttons;

    /** Eingabefeld für die Größe. */
    private final JFormattedTextField valueTextField;

    /**
     * Konstruktor.
     *
     * @param actualSize
     *            Bisherige Größe.
     * @param description
     *            Beschreibung der Einheit, dessen Größe geändert werden soll ("Radius").
     * @param rows
     *            Anzahl Zeilen in der Anordnung der Zahlen.
     * @param columns
     *            Anzahl Spalten in der Anordnung der Zahlen.
     * @param possibleSizes
     *            Menge der erlaubten auswählbaren Werte.
     * @param parentLocation
     *            Position des Rahmens der Oberfläche, vor der dieser Dialog erzeugt wird.
     * @param programImage
     *            Icon für das Programm.
     */
    public SizeChooser(int actualSize, String description, int rows, int columns,
            List<Integer> possibleSizes, Point parentLocation, Image programImage) {
        super(parentLocation, programImage, description);
        setMinimumSize(400, 250);

        this.rows = rows;
        this.columns = columns;
        this.possibleSizes = possibleSizes;

        size = NO_VALUE_SELECTED;
        differentSizesAreOk = false;
        buttons = new ArrayList<>();

        valueTextField = createValueTextField();

        fillDialog();
    }

    private JFormattedTextField createValueTextField() {
        NumberFormat fmt = NumberFormat.getInstance();
        fmt.setMaximumFractionDigits(0); // no fractions - integer only
        fmt.setMinimumFractionDigits(0); // as above
        JFormattedTextField valueTextField = new JFormattedTextField(fmt);
        GuiTools.setEditFieldColors(valueTextField);
        GuiTools.addReturnListener(valueTextField, () -> valueEntered(valueTextField.getText()));

        return valueTextField;
    }

    /** Erlaubt auch andere Größen im Texteingabefeld. */
    public void diffenrentSizesAreOk() {
        differentSizesAreOk = true;
    }

    @Override
    protected void populateDialog() {
        add(createNumberButtonsPart(), BorderLayout.CENTER);
        add(createEnterValuePart(), BorderLayout.SOUTH);
    }

    private Component createNumberButtonsPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(rows, columns));

        for (int newSize : possibleSizes) {
            JButton button = new JButton(Integer.toString(newSize));
            button.addActionListener(e -> valueEntered(newSize));
            buttons.add(button);
            panel.add(button);
        }

        return panel;
    }

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

        panel.add(valueTextField, BorderLayout.CENTER);

        return panel;
    }

    private void valueEntered(String newSizeAsString) {
        int parsedNewSize = NumberString.parseIntIgnore(newSizeAsString, NO_VALUE_SELECTED);
        valueEntered(parsedNewSize);
    }

    private void valueEntered(int newSize) {
        if (differentSizesAreOk || possibleSizes.contains(newSize)) {
            size = newSize;
            closeDialog();
        }
        else {
            GuiTools.beep();
        }
    }

    /**
     * Getter für die gewählte Größe.
     *
     * Bei Abbruch des Dialogs wird NO_VALUE_SELECTED, also -1 zurückgegeben.
     */
    public int getSize() {
        return size;
    }

    /** Setter für die gewählte Größe. */
    public void setSize(int size) {
        this.size = size;
        String sizeTitle = Integer.toString(size);
        boolean found = false;
        for (JButton button : buttons) {
            String title = button.getText();
            if (sizeTitle.equals(title)) {
                button.requestFocusInWindow();
                found = true;
                break;
            }
        }
        if (!found) {
            valueTextField.setText(sizeTitle);
            valueTextField.requestFocusInWindow();
        }
    }

}
