/* Copyright (C) 2015-2022 Stephan Kreutzer
 *
 * This file is part of option_picker_1, a submodule of the
 * digital_publishing_workflow_tools package.
 *
 * option_picker_1 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3 or any later version,
 * as published by the Free Software Foundation.
 *
 * option_picker_1 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License 3 for more details.
 *
 * You should have received a copy of the GNU Affero General Public License 3
 * along with option_picker_1. If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @file $/gui/option_picker/option_picker_1/OptionPickerDialog.java
 * @brief GUI dialog to display options and select one of them.
 * @author Stephan Kreutzer
 * @since 2015-11-14
 */



import javax.swing.*;
import java.awt.event.*;
import java.util.List;
import java.util.Vector;
import java.awt.*;
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import java.io.UnsupportedEncodingException;



public class OptionPickerDialog
  extends JDialog
  implements ActionListener
{
    public OptionPickerDialog(String title, List<OptionEntry> options)
    {
        if (title != null)
        {
            setTitle(title);
        }
        else
        {
            throw constructTermination("messageDialogNoTitle", null, null);
        }

        if (options != null)
        {
            this.options = options;
        }
        else
        {
            throw constructTermination("messageDialogNoOptions", null, null);
        }

        int optionsCount = this.options.size();

        if (optionsCount <= 0)
        {
            throw constructTermination("messageDialogNoOptions", null, null);
        }

        JPanel panelMain = new JPanel();
        GridBagLayout gridbag = new GridBagLayout();

        panelMain.setLayout(gridbag);

        GridBagConstraints gridbagConstraints = new GridBagConstraints();

        gridbagConstraints.anchor = GridBagConstraints.NORTH;
        gridbagConstraints.weightx = 1.0;
        gridbagConstraints.gridwidth = GridBagConstraints.REMAINDER;
        gridbagConstraints.fill = GridBagConstraints.HORIZONTAL;

        Vector<String> optionStrings = new Vector<String>(optionsCount);

        for (int i = 0; i < optionsCount; i++)
        {
            optionStrings.add(this.options.get(i).GetCaption());
        }

        // Java 1.6:
        this.optionsComboBox = new JComboBox(optionStrings);
        // Avoid warning in Java 1.8:
        //this.optionsComboBox = new JComboBox<String>(optionStrings);

        this.optionsComboBox.setSelectedIndex(0);
        this.optionsComboBox.addActionListener(this);

        panelMain.add(this.optionsComboBox, gridbagConstraints);
        panelMain.setBorder(BorderFactory.createEtchedBorder()); 

        getContentPane().add(panelMain, BorderLayout.NORTH); 


        JPanel panelDescription = new JPanel();
        gridbag = new GridBagLayout();

        panelDescription.setLayout(gridbag);

        gridbagConstraints = new GridBagConstraints();

        gridbagConstraints.anchor = GridBagConstraints.NORTH;
        gridbagConstraints.weightx = 1.0;
        gridbagConstraints.weighty = 1.0;
        gridbagConstraints.gridwidth = GridBagConstraints.REMAINDER;
        gridbagConstraints.gridheight = GridBagConstraints.REMAINDER;
        gridbagConstraints.fill = GridBagConstraints.BOTH;

        this.textAreaDescription = new JTextArea();
        this.textAreaDescription.setEditable(false);
        this.textAreaDescription.setLineWrap(true);
        this.textAreaDescription.setWrapStyleWord(true);
        this.textAreaDescription.setText(this.options.get(0).GetDescription());

        panelDescription.setPreferredSize(new Dimension(250, 150));

        panelDescription.add(this.textAreaDescription, gridbagConstraints);

        JScrollPane scrollPane = new JScrollPane(this.textAreaDescription);

        panelDescription.add(scrollPane, gridbagConstraints);

        panelDescription.setBorder(BorderFactory.createEtchedBorder()); 
        getContentPane().add(panelDescription, BorderLayout.CENTER);


        JPanel panelButtons = new JPanel();

        this.buttonAbort = new JButton(getI10nString("guiDialogButtonAbort"));
        buttonAbort.addActionListener(this);
        panelButtons.add(buttonAbort);

        this.buttonSelect = new JButton(getI10nString("guiDialogButtonSelect"));
        buttonSelect.addActionListener(this);
        panelButtons.add(buttonSelect);

        panelButtons.setBorder(BorderFactory.createEtchedBorder()); 
        getContentPane().add(panelButtons, BorderLayout.SOUTH);

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event)
            {
                event.getWindow().setVisible(false);
                event.getWindow().dispose();
            }
        });

        setModal(true);
        setLocation(100, 100);
        pack();
        setVisible(true);
    }

    public void actionPerformed(ActionEvent event)
    {
        if (event.getSource() instanceof JComboBox)
        {
            JComboBox comboBox = (JComboBox)event.getSource();

            int optionsCount = this.options.size();
            int selection = comboBox.getSelectedIndex();

            if (selection >= 0 &&
                selection < optionsCount)
            {
                this.textAreaDescription.setText(this.options.get(selection).GetDescription());
                return;
            }
            else
            {
                this.textAreaDescription.setText("?");
            }
        }
        else if (event.getSource() == this.buttonAbort)
        {
            this.selectedOptionId = null;
            dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
            return;
        }
        else if (event.getSource() == this.buttonSelect)
        {
            int optionsCount = this.options.size();
            int selection = this.optionsComboBox.getSelectedIndex();

            if (selection >= 0 &&
                selection < optionsCount)
            {
                this.selectedOptionId = this.options.get(selection).GetId();
                dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
                return;
            }
            else
            {
                throw constructTermination("messageDialogNoCorrespondingOptionEntryForIndex", null, null, selection, this.options.size());
            }
        }
        else
        {

        }
    }

    /**
     * @retval null Selection aborted by user.
     */
    public String GetSelectedOptionId()
    {
        return this.selectedOptionId;
    }

    private ProgramTerminationException constructTermination(String id, Exception cause, String message, Object ... arguments)
    {
        if (message == null)
        {
            if (arguments == null)
            {
                message = "option_picker_1: " + getI10nString(id);
            }
            else
            {
                message = "option_picker_1: " + getI10nStringFormatted(id, arguments);
            }
        }

        return new ProgramTerminationException(id, cause, message, L10N_BUNDLE, arguments);
    }

    public Locale getLocale()
    {
        return Locale.getDefault();
    }

    /**
     * @brief This method interprets l10n strings from a .properties file as encoded in UTF-8.
     */
    private String getI10nString(String key)
    {
        if (this.l10n == null)
        {
            this.l10n = ResourceBundle.getBundle(L10N_BUNDLE, this.getLocale());
        }

        try
        {
            return new String(this.l10n.getString(key).getBytes("UTF-8"), "UTF-8");
        }
        catch (UnsupportedEncodingException ex)
        {
            return this.l10n.getString(key);
        }
    }

    private String getI10nStringFormatted(String i10nStringName, Object ... arguments)
    {
        MessageFormat formatter = new MessageFormat("");
        formatter.setLocale(this.getLocale());

        formatter.applyPattern(getI10nString(i10nStringName));
        return formatter.format(arguments);
    }

    protected List<OptionEntry> options;
    protected String selectedOptionId = null;

    private JComboBox optionsComboBox;
    private JTextArea textAreaDescription;
    private JButton buttonAbort;
    private JButton buttonSelect;

    private static final String L10N_BUNDLE = "l10n.l10nOptionPickerDialog";
    private ResourceBundle l10n;
}
