package vismon.gui;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstants;
import vismon.util.Constants;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class OptionsPanel extends JPanel{

    public static final int AVERAGE_ISOLINES = 0;
    public static final int MEDIAN_ISOLINES = 1;

    private JPanel mainPanel;
    public static boolean showCrosshairs = true;
    public static boolean shading = true;
    public static boolean showContourLines = true;
    public static boolean seeMCTrials = false;
    public static boolean seeTrialsAllInds = false;
    public static boolean viewGrid = false;
    public static boolean viewMCUncertainty = false;
    public static int contoursBasedOn = AVERAGE_ISOLINES;

    private JCheckBox crosshairCBox;
    private JCheckBox shadingCBox;
    private JCheckBox showContourLinesCBox;
    private JCheckBox seeMCTrialsCBox;
    private JCheckBox seeTrialsAllIndsCBox;
    private JCheckBox viewGridCBox;
    private JCheckBox viewMCUncertaintyCBox;

    private JPanel colourShadingPanel;

    OptionsPanel() {
        super();
        init();
    }

    private void init() {
        mainPanel = new JPanel();
        int rowHeight = 30;
        double mainLayout[][] = {{TableLayoutConstants.FILL},           // COLUMNS
                                {rowHeight, rowHeight, rowHeight, rowHeight,
                                 rowHeight, rowHeight, rowHeight, rowHeight, rowHeight}};           // ROWS
        mainPanel.setLayout(new TableLayout(mainLayout));

        addCrosshairCheckBox();
        addContourShadingCheckBox();
        addContourShadingDescription();
        addShowContoursCheckBox();
        addMonteCarloCheckBox();
        addTrialsForAllCheckBox();
        addViewGridCheckBox();
        addViewMCUncertaintyCheckBox();
        addContourBasedOn();

        this.setLayout(new BorderLayout());
        this.add(mainPanel);
    }

    private void addCrosshairCheckBox() {
        JPanel panel = new JPanel(new BorderLayout());

        crosshairCBox = new JCheckBox("Crosshairs");
        crosshairCBox.setSelected(showCrosshairs);
        crosshairCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                showCrosshairs = crosshairCBox.isSelected();
            }
        });
        panel.add(crosshairCBox);

        mainPanel.add(panel, "0,0");
    }

    private void addContourShadingCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{200, TableLayoutConstants.FILL, 5},                             // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        shadingCBox = new JCheckBox("Contours colour-shading");
        shadingCBox.setSelected(shading);
        shadingCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                shading = shadingCBox.isSelected();
                Vismon.getVismonInstance().repaintCplomPanel();

                if (!shadingCBox.isSelected()) {
                    showContourLines = true;
                    showContourLinesCBox.setSelected(showContourLines);
                    showContourLinesCBox.setEnabled(false);
                } else {
                    showContourLinesCBox.setEnabled(true);
                }
                Vismon.getVismonInstance().repaintOptionsPanel();
            }
        });
        panel.add(shadingCBox, "0,0");

        colourShadingPanel = new PalettePanel();
        colourShadingPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 2));
        colourShadingPanel.setToolTipText("Click to change the mainColor map.");
        colourShadingPanel.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent mouseEvent) {
                ContourShadingChooser contourShadingChooser = new ContourShadingChooser();
                contourShadingChooser.run();
            }

            public void mousePressed(MouseEvent mouseEvent) {
            }

            public void mouseReleased(MouseEvent mouseEvent) {
            }

            public void mouseEntered(MouseEvent mouseEvent) {
            }

            public void mouseExited(MouseEvent mouseEvent) {
            }
        });
        panel.add(colourShadingPanel, "1,0");

        mainPanel.add(panel, "0,1");
    }

    private void addContourShadingDescription() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{10, TableLayoutConstants.FILL},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        JLabel descLabel = new JLabel("From most preferred (left) to least preferred (right)");
        Font labelFont = descLabel.getFont();
        descLabel.setFont(new Font(labelFont.getFamily(), labelFont.getStyle(), labelFont.getSize()-2));
        panel.add(descLabel, "1,0");

        mainPanel.add(panel, "0,2");
    }

    private void addShowContoursCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{20, TableLayoutConstants.FILL},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        JLabel blankLabel = new JLabel("  ");
        panel.add(blankLabel, "0,0");

        showContourLinesCBox = new JCheckBox("Show contour lines");
        showContourLinesCBox.setSelected(showContourLines);
        showContourLinesCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                showContourLines = showContourLinesCBox.isSelected();
                Vismon.getVismonInstance().repaintCplomPanel();
            }
        });
        panel.add(showContourLinesCBox, "1,0");

        mainPanel.add(panel, "0,3");
    }

    private void addMonteCarloCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{TableLayoutConstants.FILL, 40},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        seeMCTrialsCBox = new JCheckBox("See all Monte Carlo trials");
        seeMCTrialsCBox.setSelected(seeMCTrials);
        seeMCTrialsCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                seeMCTrials = seeMCTrialsCBox.isSelected();
                seeTrialsAllIndsCBox.setEnabled(seeMCTrials);
            }
        });
        panel.add(seeMCTrialsCBox, "0,0");

        JLabel questionLabel = new JLabel("    ");
        questionLabel.setIcon(new ImageIcon("images/question_white.png"));
        panel.add(questionLabel, "1,0");

        mainPanel.add(panel, "0,4");
    }

    private void addTrialsForAllCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{20, TableLayoutConstants.FILL},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        JLabel blankLabel = new JLabel("  ");
        panel.add(blankLabel, "0,0");

        seeTrialsAllIndsCBox = new JCheckBox("See trials for all indicators");
        seeTrialsAllIndsCBox.setEnabled(seeTrialsAllInds);
        seeTrialsAllIndsCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                seeTrialsAllInds = seeTrialsAllIndsCBox.isSelected();
            }
        });
        panel.add(seeTrialsAllIndsCBox, "1,0");

        mainPanel.add(panel, "0,5");
    }

    private void addViewGridCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{TableLayoutConstants.FILL, 40},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        viewGridCBox = new JCheckBox("View underlying grid");
        viewGridCBox.setSelected(viewGrid);
        viewGridCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                viewGrid = viewGridCBox.isSelected();
                viewMCUncertaintyCBox.setEnabled(viewGrid);
                Vismon.getVismonInstance().repaintCplomPanel();
            }
        });
        panel.add(viewGridCBox, "0,0");

        JLabel questionLabel = new JLabel("    ");
        questionLabel.setIcon(new ImageIcon("images/question_white.png"));
        panel.add(questionLabel, "1,0");

        mainPanel.add(panel, "0,6");
    }

    private void addViewMCUncertaintyCheckBox() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{20, TableLayoutConstants.FILL},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                   // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        JLabel blankLabel = new JLabel("  ");
        panel.add(blankLabel, "0,0");

        viewMCUncertaintyCBox = new JCheckBox("View Monte Carlo uncertainty");
        viewMCUncertaintyCBox.setEnabled(viewMCUncertainty);
        viewMCUncertaintyCBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                viewMCUncertainty = viewMCUncertaintyCBox.isSelected();
                Vismon.getVismonInstance().repaintCplomPanel();
            }
        });
        panel.add(viewMCUncertaintyCBox, "1,0");

        mainPanel.add(panel, "0,7");
    }

    private void addContourBasedOn() {
        JPanel panel = new JPanel();
        double panelLayout[][] = {{0.5, 0.5},                                 // COLUMNS
                                {TableLayoutConstants.FILL}};                 // ROWS
        panel.setLayout(new TableLayout(panelLayout));

        JLabel contourLabel = new JLabel("  Contours base on");
        panel.add(contourLabel, "0,0");

        String[] comboNames = new String[]{"Average", "Median"};
        final JComboBox comboBox = new JComboBox(comboNames);
        comboBox.setSelectedIndex(contoursBasedOn);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                contoursBasedOn = comboBox.getSelectedIndex();
                Vismon.getVismonInstance().getCplomPanel().computeCplotInterpolatedData();
                Vismon.getVismonInstance().updatePlots();
            }
        });
        panel.add(comboBox, "1,0");

        mainPanel.add(panel, "0,8");
    }

    private static OptionsPanel optionsPanelInstance;

    public static OptionsPanel getOptionsPanelInstance() {
        if (optionsPanelInstance == null) {
            optionsPanelInstance = new OptionsPanel();
        }
        return optionsPanelInstance;
    }

    public void repaintPalette() {
        colourShadingPanel.repaint();
    }

    private class PalettePanel extends JPanel {

        public PalettePanel() {
            super();
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
        }

        @Override
        protected void paintComponent(Graphics g) {
            myPaint(g);
        }

        public void myPaint(Graphics g) {

            int width = this.getWidth();
            int height = this.getHeight();

            int binNum = 8;
            int binWidth = (int) (1.0 * width / binNum);
            int shadingIndex = ContourShadingChooser.cpShadingColorIndex;

            for (int j = 0; j < binNum - 1; ++j) {
                g.setColor(Constants.getCPShadingColor(shadingIndex, j));
                g.fillRect(j * binWidth, 0, binWidth, height);
            }

            g.setColor(Constants.getCPShadingColor(shadingIndex, binNum - 1));
            g.fillRect((binNum - 1) * binWidth, 0, width - (binNum - 1) * binWidth, height);
        }
    }
}

