/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.installer.common;

import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import javax.swing.text.NumberFormatter;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.text.NumberFormat;
import java.text.ParseException;

import static org.jboss.installer.screens.DefaultScreen.LEFT_COLUMN_WEIGHT;
import static org.jboss.installer.screens.DefaultScreen.NO_INSET;
import static org.jboss.installer.screens.DefaultScreen.RIGHT_COLUMN_WEIGHT;
import static org.jboss.installer.screens.DefaultScreen.RIGHT_INDENT_INSET;

public class UiResources {

    public static final Color HEADING_PANEL_BACKGROUND = new Color(0x212121);
    public static final Color SIDE_NAV_BG_COLOR = new Color(0xF5F5F5);
    public static final Color inactiveTextField = new Color(0xF5F5F5);
    public static final ImageIcon DONE_ICON = new ImageIcon(UiResources.class.getResource("/img/check.png"));

    public static GridBagConstraints initializeConstraints() {
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridy = 0;
        c.gridx = 0;
        c.weightx = 2;
        return c;
    }

    public static JPasswordField createPasswordField() {
        final JPasswordField passwordField = new JPasswordField();
        passwordField.setFont(FontResources.getOpenSansRegular());
        return withScrollBarListener(passwordField);
    }

    public static JTextField createTextField(String text) {
        final JTextField textField = new JTextField(text);
        textField.setFont(FontResources.getOpenSansRegular());
        return withScrollBarListener(textField);
    }

    public static JTextField createNumberField(int value) {
        final JTextField textField = new JFormattedTextField(getNumberFormatter());
        textField.setText(value + "");
        textField.setFont(FontResources.getOpenSansRegular());
        return withScrollBarListener(textField);
    }

    private static NumberFormatter getNumberFormatter() {
        NumberFormat format = NumberFormat.getIntegerInstance();
        format.setGroupingUsed(false);
        NumberFormatter formatter = new NumberFormatter(format) {
            @Override
            public Object stringToValue(String text) throws ParseException {
                if (text.length() == 0)
                    return null;
                return super.stringToValue(text);
            }
        };
        formatter.setValueClass(Integer.class);
        formatter.setMinimum(0);
        formatter.setAllowsInvalid(false);
        formatter.setCommitsOnValidEdit(true);
        return formatter;
    }

    public static JButton createButton(String text, ActionListener listener) {
        final JButton button = new JButton(text);
        button.setFont(FontResources.getOpenSansRegular());
        if (listener != null) {
            button.addActionListener(listener);
        }
        return withScrollBarListener(button);
    }

    public static JLabel createFieldLabel(String text) {
        // add html tags to enable text wrapping
        if (!text.startsWith("<html")) {
            text = "<html>" + text + "</html>";
        }

        JLabel label = new JLabel(text);
        label.setFont(FontResources.getOpenSansRegular());
        return label;
    }

    public static JLabel createFieldLabelWithColonSuffix(String text) {
        return createFieldLabel(text + ":");
    }

    public static JComboBox<String> createDropdown(String[] values) {
        JComboBox<String> comboBox = new JComboBox<>(values);
        comboBox.setFont(FontResources.getOpenSansRegular());
        comboBox.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                // JBEAP-26165 - if the component was moved while the popup is visible, it's possible that the popup is no
                // longer aligned with the component. In this case, close and re-open the popup to re-align it.
                if (comboBox.isPopupVisible()) {
                    comboBox.hidePopup();
                    comboBox.showPopup();
                }
            }

            @Override
            public void componentShown(ComponentEvent e) {

            }

            @Override
            public void componentHidden(ComponentEvent e) {

            }
        });
        return withScrollBarListener(comboBox);
    }

    public static void addField(JPanel content, GridBagConstraints c, String labelText, JComponent textField) {
        c.insets = RIGHT_INDENT_INSET;
        c.gridy++;
        c.gridx = 0;
        c.weightx = LEFT_COLUMN_WEIGHT;
        content.add(createFieldLabelWithColonSuffix(labelText), c);

        c.gridx = 1;
        c.weightx = RIGHT_COLUMN_WEIGHT;
        content.add(textField, c);
        c.gridx = 0;
        c.weightx = 1;
        c.insets = NO_INSET;
    }

    public static void addField(JPanel content, GridBagConstraints c, String labelText, String tooltipText, JComponent textField) {
        c.insets = RIGHT_INDENT_INSET;
        c.gridy++;
        c.gridx = 0;
        c.weightx = LEFT_COLUMN_WEIGHT;
        final JLabel label = createFieldLabelWithColonSuffix(labelText);
        content.add(label, c);

        c.gridx = 1;
        c.weightx = RIGHT_COLUMN_WEIGHT;
        content.add(textField, c);
        c.gridx = 0;
        c.weightx = 1;
        c.insets = NO_INSET;

        setTooltip(label, tooltipText);
        setTooltip(textField, tooltipText);
    }

    public static void setTooltip(JComponent comp, String tooltipText) {
        final String tooltip = "<html><p width=\"200\">" + tooltipText + "</p></html>";
        comp.setToolTipText(tooltip);
    }

    public static JRadioButton createRadioButton(String text, boolean selected) {
        JRadioButton radioButton = new JRadioButton(text, selected);
        radioButton.setFont(FontResources.getOpenSansRegular());
        return withScrollBarListener(radioButton);
    }

    public static CompoundBorder spacedBorder() {
        final Border lineBorder = BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true);
        return BorderFactory.createCompoundBorder(lineBorder, BorderFactory.createEmptyBorder(10, 10, 10, 10));
    }

    public static <T extends JComponent> T withScrollBarListener(T component) {
        component.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (e.getComponent() == null || e.getComponent().getParent() == null) {
                    return;
                }

                if (e.getComponent().getParent() instanceof JComponent) {
                    ((JComponent) e.getComponent().getParent()).scrollRectToVisible(e.getComponent().getBounds());
                }
            }
        });
        return component;
    }

    public static String readTextValue(FileChooserPanel fileChooser) {
        if (fileChooser.getText() == null) {
            return null;
        }
        if (fileChooser.getText().trim().isEmpty()) {
            return null;
        }
        return fileChooser.getText();
    }

    public static String readTextValue(JTextComponent textField) {
        if (textField.getText() == null) {
            return null;
        }
        if (textField.getText().trim().isEmpty()) {
            return null;
        }
        return textField.getText().trim();
    }
}
