package vismon.gui;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstants;
import vismon.component.VerticalLabelUI;
import vismon.data.Indicator;
import vismon.data.MngOption;
import vismon.data.Session;
import vismon.plot.ContourPlot;
import vismon.util.Constants;
import vismon.util.Util;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;

public class CplomPanel extends JPanel {

    private JPanel panel;
    private double[][] panelLayout;

    private JPanel centerPanel;
    private double[][] centerPanelLayout;

    private JPopupMenu popup;

    private ActionListener menuListener;
    private JLabel mngOption0Label;
    private JLabel mngOption1Label;
    private List<JLabel> indicatorLabelList;
    private List<ContourPlot> contourPlotList;
    private ContourPlot cursorOnCplotPanel;

    private List<JMenuItem> addPlotMenuItems;

    CplomPanel() {
        super();

        indicatorLabelList = new ArrayList<JLabel>();
        contourPlotList = new ArrayList<ContourPlot>();
        addPlotMenuItems = new ArrayList<JMenuItem>();

        init();

        popup = new JPopupMenu();
        menuListener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                if (event.getActionCommand().equals("Show all Contour Plots")) {
                    showAllPlots();
                    Vismon.getVismonInstance().getTradeoffsIndicatorsPanel().setAllCBoxSelected(true);
                } else {
                    for (int i = 0; i < Session.getIndicatorNum(); ++i) {
                        if (event.getActionCommand().equals("   Show " + Session.getIndicator(i).getName() + " Contour Plot")) {
                            Session.getIndicator(i).setVisible(true);
                            Vismon.getVismonInstance().updateIndicatorVisibility();
                        }
                    }
                }
            }
        };

        JMenuItem item;
        popup.add(item = new JMenuItem("Show all Contour Plots"));
        item.setHorizontalTextPosition(JMenuItem.RIGHT);
        item.addActionListener(menuListener);

        popup.setBorder(new BevelBorder(BevelBorder.RAISED));
    }

    protected void init() {
        panel = new JPanel();
        panel.setBackground(Color.WHITE);

        centerPanel = new JPanel();
        centerPanel.setBackground(Color.WHITE);
        centerPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                    showPopup(mouseEvent);
            }

            @Override
            public void mousePressed(MouseEvent mouseEvent) {
                if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                    showPopup(mouseEvent);
            }

            @Override
            public void mouseReleased(MouseEvent mouseEvent) {
                if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                    showPopup(mouseEvent);
            }

            private void showPopup(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    if (getPopup() != null)
                        getPopup().show(centerPanel, e.getX(), e.getY());
                }
            }
        });

        this.setLayout(new BorderLayout());
        //this.add(centerPanel);
        this.add(panel);
    }

    private void setPanelLayout() {
        int borderGap = 20;

        panelLayout = new double[2][];
        panelLayout[0] = new double[2];
        panelLayout[1] = new double[2];

        panelLayout[0][0] = borderGap;
        panelLayout[0][1] = TableLayoutConstants.FILL;

        panelLayout[1][0] = TableLayoutConstants.FILL;
        panelLayout[1][1] = borderGap;

        panel.setLayout(new TableLayout(panelLayout));
    }

    private void setCenterPanelLayout() {
        int colNum = Session.getIndicatorDrawnColNum();
        int rowNum = Session.getIndicatorDrawnRowNum();

        int plotNameGap = 15;
        int blankGap = 1;

        centerPanelLayout = new double[2][];
        centerPanelLayout[0] = new double[2 * colNum + 1];
        centerPanelLayout[1] = new double[3 * rowNum + 1];

        centerPanelLayout[0][0] = blankGap;                              //LEFT
        for (int i = 0; i < colNum; ++i) {
            centerPanelLayout[0][2 * i + 1] = TableLayoutConstants.FILL;
            centerPanelLayout[0][2 * i + 2] = blankGap;
        }

        centerPanelLayout[1][0] = blankGap;                              //TOP
        for (int i = 0; i < rowNum; ++i) {
            centerPanelLayout[1][3 * i + 1] = plotNameGap;
            centerPanelLayout[1][3 * i + 2] = TableLayoutConstants.FILL;
            centerPanelLayout[1][3 * i + 3] = blankGap;
        }
        centerPanel.setLayout(new TableLayout(centerPanelLayout));
    }

    public void createLabels() {
        mngOption0Label = new JLabel(Session.getMngOption(0).getName(), SwingConstants.CENTER);
        mngOption0Label.setFont(Constants.OVERVIEW_TITLE_FONT);
        mngOption0Label.setForeground(Constants.MAIN_COLOR);

        mngOption1Label = new JLabel(Session.getMngOption(1).getName(), SwingConstants.CENTER);
        mngOption1Label.setUI(new VerticalLabelUI(false));
        mngOption1Label.setFont(Constants.OVERVIEW_TITLE_FONT);
        mngOption1Label.setForeground(Constants.MAIN_COLOR);

        for (int i = 0; i < Session.getIndicatorNum(); ++i) {
            JLabel label = new JLabel("", SwingConstants.CENTER);
            indicatorLabelList.add(label);
        }
    }

    public void createPlotPanels() {
        for (int i = 0; i < Session.getIndicatorNum(); ++i) {
            final ContourPlot cplotPanel = new ContourPlot(Session.getMngOption(0), Session.getMngOption(1),
                    Session.getIndicator(i));
            cplotPanel.setBackground(Color.WHITE);
            cplotPanel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent mouseEvent) {
                    if (mouseEvent.getButton() == MouseEvent.BUTTON1) {
                        cplotPanel.createScenario();
                    } else if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                        showPopup(mouseEvent);
                }

                @Override
                public void mousePressed(MouseEvent mouseEvent) {
                    if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                        showPopup(mouseEvent);
                }

                @Override
                public void mouseReleased(MouseEvent mouseEvent) {
                    if (mouseEvent.getButton() == MouseEvent.BUTTON3)
                        showPopup(mouseEvent);
                }

                private void showPopup(MouseEvent e) {
                    if (e.isPopupTrigger()) {
                        if (cplotPanel.getPopup() != null)
                            cplotPanel.getPopup().show(cplotPanel, e.getX(), e.getY());
                    }
                }
            });

            cplotPanel.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent mouseEvent) {
                    cplotPanel.setCursorLocalX(mouseEvent.getX());
                    cplotPanel.setCursorLocalY(mouseEvent.getY());
                    cplotPanel.calcCursorXY(mouseEvent);
                    cplotPanel.setCrossHairScenarion();
                    cplotPanel.showScenarioName();

                    cursorOnCplotPanel = cplotPanel;

                    setCplotsSeeMCTrial();
                    repaintAllGUIs();
                }
            });

            cplotPanel.computeInterpolatedData();
            contourPlotList.add(cplotPanel);
        }
    }

    public void addGUI() {
        setPanelLayout();
        setCenterPanelLayout();
        panel.add(centerPanel, "1,0");

        addMngOptionLabels();
        addIndicatorLabels();
        addCploms();
    }

    public void addMngOptionLabels() {
        panel.add(mngOption0Label, "1,1");
        panel.add(mngOption1Label, "0,0");
    }

    public void addIndicatorLabels() {
        for (Indicator indicator : Session.getIndicators()) {
            if (!indicator.isVisible())
                continue;

            int[] colRow = Session.getIndicatorRowColPosition(indicator);
            int r = colRow[0];
            int c = colRow[1];

            String label = indicator.getShortName();

            JLabel nameLabel = indicatorLabelList.get(Session.getIndicatorRank(indicator));
            nameLabel.setText(label);
            nameLabel.setForeground(Constants.MAIN_COLOR);
            nameLabel.setFont(Constants.OVERVIEW_TITLE_FONT);
            centerPanel.add(nameLabel, (1 + 2 * c) + "," + (1 + 3 * r));
        }

        /*for (int r = 0; r < rowNum; ++r) {
            for (int c = 0; c < colNum; ++c) {
                Indicator indicator = Session.getIndicator(r*colNum+c);
                String label = indicator.getShortName();

                JLabel nameLabel = indicatorLabelList.get(r*colNum+c);
                nameLabel.setText(label);
                nameLabel.setForeground(Constants.MAIN_COLOR);
                nameLabel.setFont(Constants.OVERVIEW_TITLE_FONT);
                centerPanel.add(nameLabel, (1 + 2 * c) + "," + (1 + 3 * r));
            }
        }*/
    }

    public void addCploms() {
        for (Indicator indicator : Session.getIndicators()) {
            if (!indicator.isVisible())
                continue;

            int[] colRow = Session.getIndicatorRowColPosition(indicator);
            int r = colRow[0];
            int c = colRow[1];

            ContourPlot cplot = contourPlotList.get(Session.getIndicatorRank(indicator));
            centerPanel.add(cplot, (1 + 2 * c) + "," + (2 + 3 * r));
            cplot.repaint();
        }

        /*for (int r = 0; r < rowNum; ++r) {
            for (int c = 0; c < colNum; ++c) {
                centerPanel.add(contourPlotList.get(r*colNum+c), (1+2*c) + "," + (2+3*r));
                contourPlotList.get(r*colNum+c).repaint();
            }
        }*/
    }

    public void repaintAllGUIs() {
        MngOption mngOption0 = Session.getMngOption(0);
        MngOption mngOption1 = Session.getMngOption(1);
        if (Session.getCrosshairScenario() != null) {
            String mng0Text = mngOption0.getName() + ": " +
                    Util.roundToOneHundredth(Session.getCrosshairScenario().getMngAction().getMngValue(mngOption0));
            mngOption0Label.setText(mng0Text);

            String mng1Text = mngOption1.getName() + ": " +
                    Util.roundToOneHundredth(Session.getCrosshairScenario().getMngAction().getMngValue(mngOption1));
            mngOption1Label.setText(mng1Text);

            for (int i = 0; i < Session.getIndicatorNum(); ++i) {
                JLabel label = indicatorLabelList.get(i);
                Indicator indicator = Session.getIndicator(i);
                String labelText = indicator.getShortName() + ": " +
                        Util.roundToOneTenth(Session.getCrosshairScenario().getAverageValue(indicator));
                label.setText(labelText);
            }
        } else {
            mngOption0Label.setText(mngOption0.getName());

            mngOption1Label.setText(mngOption1.getName());

            for (int i = 0; i < Session.getIndicatorNum(); ++i) {
                JLabel label = indicatorLabelList.get(i);
                Indicator indicator = Session.getIndicator(i);
                String labelText = indicator.getShortName();
                label.setText(labelText);
            }
        }

        for (ContourPlot cplot : contourPlotList)
            cplot.repaint();
    }

    public void repaintPanelLayout() {
        setCenterPanelLayout();
        addIndicatorLabels();
        addCploms();
    }

    public void showAllPlots() {
        for (int i = 0; i < Session.getIndicatorNum(); ++i)
            Session.getIndicator(i).setVisible(true);
        Vismon.getVismonInstance().updateIndicatorVisibility();
    }

    public JPopupMenu getPopup() {
        return popup;
    }

    public void addPopupMenuItems() {
        for (int i = 0; i < Session.getIndicatorNum(); ++i) {
            JMenuItem menuItem;
            popup.add(menuItem = new JMenuItem("   Show " + Session.getIndicator(i).getName() + " Contour Plot"));
            menuItem.setHorizontalTextPosition(JMenuItem.RIGHT);
            menuItem.addActionListener(menuListener);
            menuItem.setVisible(false);

            addPlotMenuItems.add(menuItem);
        }
    }

    public void setContourPlotVisible(int rank, boolean visible) {
        contourPlotList.get(rank).setVisible(visible);
    }

    public void setPlotMenuItemVisible(int rank, boolean visible) {
        addPlotMenuItems.get(rank).setVisible(visible);
    }

    public void computeCplotInterpolatedData() {
        for (ContourPlot cplot : contourPlotList)
            cplot.computeInterpolatedData();
    }

    public void setCplotsSeeMCTrial() {
        for (ContourPlot cplot : contourPlotList)
            cplot.setSeeMCTrials(false);
        cursorOnCplotPanel.setSeeMCTrials(true);
    }

}
