package de.renew.draw.ui.impl.dialogs;

import java.awt.Component;
import java.util.function.Consumer;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import de.renew.draw.ui.ontology.dialogs.DialogMessageType;
import de.renew.draw.ui.ontology.dialogs.DialogOptionType;
import de.renew.draw.ui.ontology.dialogs.OptionDialog;
import de.renew.draw.ui.ontology.dialogs.OptionDialogBuilder;

/**
 * The implementation of the option dialog.
 */
final class OptionDialogImpl extends DialogImpl<OptionDialogBuilder> implements OptionDialog {

    private final DialogOptionType _optionType;
    private final Object[] _selectionValues;
    private final Object _initialSelectionValue;

    private OptionDialogImpl(
        Component parentComponent, String title, DialogMessageType messageType, Icon icon,
        Object message, DialogOptionType optionType, Object[] selectionValues,
        Object initialSelectionValue)
    {
        super(parentComponent, title, messageType, icon, message);
        this._optionType = optionType;
        this._selectionValues = selectionValues;
        this._initialSelectionValue = initialSelectionValue;
    }

    @Override
    public int show() {

        if (this._title != null || this._icon != null || this._selectionValues != null
            || this._initialSelectionValue != null) {

            return JOptionPane.showOptionDialog(
                this._parentComponent, this._message, this._title,
                DialogAbstractionUtil.convertToSwingOptionType(this._optionType),
                DialogAbstractionUtil.convertToSwingMessageType(this._messageType), this._icon,
                this._selectionValues, this._initialSelectionValue);

        } else {

            return JOptionPane.showConfirmDialog(this._parentComponent, this._message);

        }

    }

    @Override
    public void showAsync(Consumer<Integer> onOptionSelected) {

        SwingUtilities.invokeLater(() -> onOptionSelected.accept(show()));

    }

    @Override
    public OptionDialogBuilder toNewBuilder() {
        return new OptionDialogBuilderImpl().setParentComponent(this._parentComponent)
            .setTitle(this._title).setMessageType(this._messageType).setIcon(this._icon)
            .setMessage(this._message).setSelectionValues(this._selectionValues)
            .setInitialSelectionValue(this._initialSelectionValue).setOptionType(this._optionType);
    }

    /**
     * The builder of the option dialog.
     */
    static final class OptionDialogBuilderImpl extends DialogBuilderImpl<OptionDialogBuilder>
        implements OptionDialogBuilder
    {

        private DialogOptionType _optionType = DialogOptionType.YES_NO_CANCEL_OPTION;
        private Object[] _selectionValues;
        private Object _initialSelectionValue;

        /**
         * Creates a new instance of the OptionDialogBuilder, used to create {@link OptionDialog}s.
         */
        OptionDialogBuilderImpl() {}

        @Override
        public OptionDialogBuilderImpl setSelectionValues(Object[] selectionValues) {
            this._selectionValues = selectionValues;
            return this;
        }

        @Override
        public OptionDialogBuilderImpl setInitialSelectionValue(Object initialSelectionValue) {
            this._initialSelectionValue = initialSelectionValue;
            return this;
        }

        @Override
        public OptionDialogBuilderImpl setOptionType(DialogOptionType optionType) {
            this._optionType = optionType;
            return this;
        }

        @Override
        protected OptionDialogBuilderImpl self() {
            return this;
        }

        @Override
        public OptionDialogImpl build() {
            return new OptionDialogImpl(
                this._parentComponent, this._title, this._messageType, this._icon, this._message,
                this._optionType, this._selectionValues, this._initialSelectionValue);
        }

    }

}
