package net.sf.jabref.gui.preftabs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JPanel;

import net.sf.jabref.Globals;
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.preferences.JabRefPreferences;

import com.jgoodies.forms.builder.FormBuilder;
import com.jgoodies.forms.layout.FormLayout;

public class ColorSetupPanel extends JPanel {

    private static final int ICON_WIDTH = 30;
    private static final int ICON_HEIGHT = 20;
    private final List<ColorButton> buttons = new ArrayList<>();


    public ColorSetupPanel(JCheckBox colorCodes, JCheckBox resolvedColorCodes, JCheckBox showGrid) {

        FormLayout layout = new FormLayout(
                "30dlu, 4dlu, fill:pref, 4dlu, fill:pref, 8dlu, 30dlu, 4dlu, fill:pref, 4dlu, fill:pref",
                "pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref");
        FormBuilder builder = FormBuilder.create().layout(layout);

        buttons.add(new ColorButton(JabRefPreferences.TABLE_TEXT, Localization.lang("Table text color")));
        buttons.add(new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND0,
                Localization.lang("Marking color %0", "1")));
        buttons.add(new ColorButton(JabRefPreferences.TABLE_BACKGROUND, Localization.lang("Table background color")));
        buttons.add(new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND1,
                Localization.lang("Marking color %0", "2")));
        buttons.add(new ColorButton(JabRefPreferences.TABLE_REQ_FIELD_BACKGROUND,
                Localization.lang("Background color for required fields"), colorCodes));
        buttons.add(new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND2,
                Localization.lang("Marking color %0", "3")));
        buttons.add(new ColorButton(JabRefPreferences.TABLE_OPT_FIELD_BACKGROUND,
                Localization.lang("Background color for optional fields"), colorCodes));
        buttons.add(new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND3,
                Localization.lang("Marking color %0", "4")));
        buttons.add(new ColorButton(JabRefPreferences.INCOMPLETE_ENTRY_BACKGROUND,
                Localization.lang("Color for marking incomplete entries")));
        buttons.add(new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND4,
                Localization.lang("Marking color %0", "5")));
        buttons.add(new ColorButton(JabRefPreferences.GRID_COLOR, Localization.lang("Table grid color"), showGrid));
        buttons.add(
                new ColorButton(JabRefPreferences.MARKED_ENTRY_BACKGROUND5, Localization.lang("Import marking color")));

        buttons.add(new ColorButton(JabRefPreferences.FIELD_EDITOR_TEXT_COLOR,
                Localization.lang("Entry editor font color")));
        buttons.add(new ColorButton(JabRefPreferences.VALID_FIELD_BACKGROUND_COLOR,
                Localization.lang("Entry editor background color")));
        buttons.add(new ColorButton(JabRefPreferences.ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR,
                Localization.lang("Entry editor active background color")));
        buttons.add(new ColorButton(JabRefPreferences.INVALID_FIELD_BACKGROUND_COLOR,
                Localization.lang("Entry editor invalid field color")));
        buttons.add(new ColorButton(JabRefPreferences.TABLE_RESOLVED_FIELD_BACKGROUND,
                Localization.lang("Background color for resolved fields"), resolvedColorCodes));

        int rowcnt = 0;
        int col = 0;
        int row;
        for (ColorButton but : buttons) {
            row = (2*(rowcnt/2)) + 1; // == 2*floor(rowcnt/2) + 1
            builder.add((JButton)but).xy((6*col)+1, row);
            builder.add(but.getDefaultButton()).xy((6*col)+3, row);
            builder.add(but.getName()).xy((6*col)+5, row);
            but.addActionListener(new ColorButtonListener(but));
            col = 1-col;  // Change 0 -> 1 -> 0 ...
            rowcnt++;
        }

        setLayout(new BorderLayout());
        add(builder.getPanel(), BorderLayout.CENTER);

        setValues();

    }

    public void setValues() {
        for (ColorButton but : buttons) {
            but.setColor(Globals.prefs.getColor(but.getKey()));
        }

    }

    public void storeSettings() {
        for (ColorButton but : buttons) {
            Globals.prefs.putColor(but.getKey(), but.getColor());
        }
    }


    static class ColorButtonListener implements ActionListener {

        private final ColorButton button;


        public ColorButtonListener(ColorButton button) {
            this.button = button;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Color chosen = JColorChooser.showDialog(null, button.getName(), button.getColor());
            if (chosen != null) {
                button.setColor(chosen);
                button.getCheckBox().ifPresent(checkBox -> checkBox.setSelected(true));
            }
        }
    }

    /**
     * A button to display the chosen color, and hold key information about a color setting.
     * Includes a method to produce a Default button for this setting.
     */
    static class ColorButton extends JButton implements Icon {
        private Color color = Color.white;
        private final String key;
        private final String name;
        private Optional<JCheckBox> checkBox = Optional.empty();

        public ColorButton(String key, String name, JCheckBox checkBox) {
            this(key, name);
            this.checkBox = Optional.of(checkBox);
        }

        public ColorButton(String key, String name) {
            setIcon(this);
            this.key = key;
            this.name = name;
            setBorder(BorderFactory.createRaisedBevelBorder());
        }

        public JButton getDefaultButton() {
            JButton toDefault = new JButton(Localization.lang("Default"));
            toDefault.addActionListener(e -> {
                setColor(Globals.prefs.getDefaultColor(key));
                repaint();
            });
            return toDefault;
        }

        public String getKey() {
            return key;
        }

        @Override
        public String getName() {
            return name;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        @Override
        public void paintIcon(Component c, Graphics g, int x, int y) {
            Rectangle r = g.getClipBounds();
            g.setColor(color);
            g.fillRect(r.x, r.y, r.width, r.height);
        }

        @Override
        public int getIconWidth() {
            return ColorSetupPanel.ICON_WIDTH;
        }

        @Override
        public int getIconHeight() {
            return ColorSetupPanel.ICON_HEIGHT;
        }

        public Optional<JCheckBox> getCheckBox() {
            return checkBox;
        }
    }

}
