/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.log4j.chainsaw.color;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
import org.apache.log4j.chainsaw.ChainsawConstants;
import org.apache.log4j.chainsaw.ExpressionRuleContext;
import org.apache.log4j.chainsaw.filter.FilterModel;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.chainsaw.icons.ChainsawIcons;
import org.apache.log4j.rule.ColorRule;
import org.apache.log4j.rule.ExpressionRule;
import org.apache.log4j.rule.Rule;


/**
 * Panel which updates a RuleColorizer, allowing the user to build expression-based
 * color rules.
 * 
 * TODO: examine ColorPanel/RuleColorizer/LogPanel listeners and interactions
 *
 * @author Scott Deboy &lt;sdeboy@apache.org&gt;
 */
public class ColorPanel extends JPanel
{
  private static final String DEFAULT_STATUS = "<html>Double click a rule field to edit the rule</html>";
  private final String currentRuleSet = "Default";

  private RuleColorizer colorizer;
  private JPanel rulesPanel;
  private FilterModel filterModel;
  private DefaultTableModel tableModel;
  private JScrollPane tableScrollPane;
  private JTable table;
  private ActionListener closeListener;
  private JLabel statusBar;
  private Vector columns;
  private final String noTab = "None";
  private DefaultComboBoxModel logPanelColorizersModel;
  private Map allLogPanelColorizers;
  private RuleColorizer currentLogPanelColorizer;
  private JTable searchTable;
  private DefaultTableModel searchTableModel;
  private Vector searchColumns;
  private Vector searchDataVector;
  private Vector searchDataVectorEntry;

  private JTable alternatingColorTable;
  private DefaultTableModel alternatingColorTableModel;
  private Vector alternatingColorColumns;
  private Vector alternatingColorDataVector;
  private Vector alternatingColorDataVectorEntry;
  private ApplicationPreferenceModel applicationPreferenceModel;
  private JCheckBox bypassSearchColorsCheckBox;

  public ColorPanel(final RuleColorizer currentLogPanelColorizer, final FilterModel filterModel,
                      final Map allLogPanelColorizers, final ApplicationPreferenceModel applicationPreferenceModel) {
    super(new BorderLayout());

    this.currentLogPanelColorizer = currentLogPanelColorizer;
    this.colorizer = currentLogPanelColorizer;
    this.filterModel = filterModel;
    this.allLogPanelColorizers = allLogPanelColorizers;
    this.applicationPreferenceModel = applicationPreferenceModel;

    currentLogPanelColorizer.addPropertyChangeListener(
    	      "colorrule",
            evt -> updateColors());

    tableModel = new DefaultTableModel();
    table = new JTable(tableModel);
    table.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);

    searchTableModel = new DefaultTableModel();
    searchTable = new JTable(searchTableModel);
    searchTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
    searchTable.setPreferredScrollableViewportSize(new Dimension(30, 30));

    alternatingColorTableModel = new DefaultTableModel();
    alternatingColorTable = new JTable(alternatingColorTableModel);
    alternatingColorTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
    alternatingColorTable.setPreferredScrollableViewportSize(new Dimension(30, 30));

    columns = new Vector();
    columns.add("Expression");
    columns.add("Background");
    columns.add("Foreground");

    searchColumns = new Vector();
    searchColumns.add("Background");
    searchColumns.add("Foreground");

    alternatingColorColumns = new Vector();
    alternatingColorColumns.add("Background");
    alternatingColorColumns.add("Foreground");

    //searchtable contains only a single-entry vector containing a two-item vector (foreground, background)
    searchDataVector = new Vector();
    searchDataVectorEntry = new Vector();
    searchDataVectorEntry.add(applicationPreferenceModel.getSearchBackgroundColor());
    searchDataVectorEntry.add(applicationPreferenceModel.getSearchForegroundColor());
    searchDataVector.add(searchDataVectorEntry);
    searchTableModel.setDataVector(searchDataVector, searchColumns);

    alternatingColorDataVector = new Vector();
    alternatingColorDataVectorEntry = new Vector();
    alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorBackgroundColor());
    alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorForegroundColor());
    alternatingColorDataVector.add(alternatingColorDataVectorEntry);
    alternatingColorTableModel.setDataVector(alternatingColorDataVector, alternatingColorColumns);

    table.setPreferredScrollableViewportSize(new Dimension(525, 200));
    tableScrollPane = new JScrollPane(table);

    Vector data = getColorizerVector();
    tableModel.setDataVector(data, columns);

    table.sizeColumnsToFit(0);
    table.getColumnModel().getColumn(1).setPreferredWidth(80);
    table.getColumnModel().getColumn(2).setPreferredWidth(80);
    table.getColumnModel().getColumn(1).setMaxWidth(80);
    table.getColumnModel().getColumn(2).setMaxWidth(80);

    searchTable.sizeColumnsToFit(0);
    searchTable.getColumnModel().getColumn(0).setPreferredWidth(80);
    searchTable.getColumnModel().getColumn(1).setPreferredWidth(80);
    searchTable.getColumnModel().getColumn(0).setMaxWidth(80);
    searchTable.getColumnModel().getColumn(1).setMaxWidth(80);
    //building color choosers needs to be done on the EDT
    SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(searchTable));

    alternatingColorTable.sizeColumnsToFit(0);
    alternatingColorTable.getColumnModel().getColumn(0).setPreferredWidth(80);
    alternatingColorTable.getColumnModel().getColumn(1).setPreferredWidth(80);
    alternatingColorTable.getColumnModel().getColumn(0).setMaxWidth(80);
    alternatingColorTable.getColumnModel().getColumn(1).setMaxWidth(80);
    //building color choosers needs to be done on the EDT
    SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(alternatingColorTable));

    configureTable();

    statusBar = new JLabel(DEFAULT_STATUS);

    rulesPanel = buildRulesPanel();
    rulesPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

    JPanel rightPanel = new JPanel(new BorderLayout());

    JPanel rightOuterPanel = new JPanel();
    rightOuterPanel.setLayout(
      new BoxLayout(rightOuterPanel, BoxLayout.X_AXIS));
    rightOuterPanel.add(Box.createHorizontalStrut(10));

    JPanel southPanel = new JPanel();
    southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS));
    southPanel.add(Box.createVerticalStrut(5));
    southPanel.add(Box.createVerticalStrut(5));
    JPanel searchAndAlternatingColorPanel = buildSearchAndAlternatingColorPanel();
    JPanel bypassSearchColorsPanel = buildBypassSearchColorsPanel();
    bypassSearchColorsCheckBox.setSelected(applicationPreferenceModel.isBypassSearchColors());

    JPanel globalLabelPanel = new JPanel();
    globalLabelPanel.setLayout(new BoxLayout(globalLabelPanel, BoxLayout.X_AXIS));
    JLabel globalLabel = new JLabel("Global colors:");
    globalLabelPanel.add(globalLabel);
    globalLabelPanel.add(Box.createHorizontalGlue());
    southPanel.add(globalLabelPanel);
    southPanel.add(searchAndAlternatingColorPanel);
    southPanel.add(bypassSearchColorsPanel);
    southPanel.add(Box.createVerticalStrut(5));
    JPanel closePanel = buildClosePanel();
    southPanel.add(closePanel);

    JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    statusPanel.add(statusBar);
    southPanel.add(statusPanel);
    rightPanel.add(rulesPanel, BorderLayout.CENTER);
    rightPanel.add(southPanel, BorderLayout.SOUTH);
    rightOuterPanel.add(rightPanel);

    JPanel topPanel = new JPanel();
    topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));

    JLabel selectText = new JLabel("Apply a tab's colors");
    topPanel.add(selectText);
    topPanel.add(Box.createHorizontalStrut(5));

    logPanelColorizersModel = new DefaultComboBoxModel();
    final JComboBox loadPanelColorizersComboBox = new JComboBox(logPanelColorizersModel);
    loadLogPanelColorizers();

    topPanel.add(loadPanelColorizersComboBox);

    topPanel.add(Box.createHorizontalStrut(5));
    final Action copyRulesAction = new AbstractAction() {
        public void actionPerformed(ActionEvent e)
          {
              tableModel.getDataVector().clear();
              Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
              if (selectedItem != null) {
                RuleColorizer sourceColorizer = (RuleColorizer) allLogPanelColorizers.get(selectedItem.toString());
                colorizer.setRules(sourceColorizer.getRules());
                updateColors();
              }
          }
      };
        
      loadPanelColorizersComboBox.addActionListener(e -> {
          Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
          if (selectedItem != null) {
            String selectedColorizerName = selectedItem.toString();
            copyRulesAction.setEnabled(!(noTab.equals(selectedColorizerName)));
          }
      });

    copyRulesAction.putValue(Action.NAME, "Copy color rules");
    copyRulesAction.setEnabled(!(noTab.equals(loadPanelColorizersComboBox.getSelectedItem())));

    JButton copyRulesButton = new JButton(copyRulesAction);
    topPanel.add(copyRulesButton);

    add(topPanel, BorderLayout.NORTH);
    add(rightOuterPanel, BorderLayout.CENTER);
    if (table.getRowCount() > 0) {
        table.getSelectionModel().setSelectionInterval(0, 0);
    }
  }

  public void loadLogPanelColorizers() {
      if (logPanelColorizersModel.getIndexOf(noTab) == -1) {
        logPanelColorizersModel.addElement(noTab);
      }
      for (Object o : allLogPanelColorizers.entrySet()) {
          Map.Entry entry = (Map.Entry) o;
          if (!entry.getValue().equals(currentLogPanelColorizer) && (logPanelColorizersModel.getIndexOf(entry.getKey()) == -1)) {
              logPanelColorizersModel.addElement(entry.getKey());
          }
      }
      //update search and alternating colors, since they may have changed from another color panel
      searchDataVectorEntry.set(0, applicationPreferenceModel.getSearchBackgroundColor());
      searchDataVectorEntry.set(1, applicationPreferenceModel.getSearchForegroundColor());
      alternatingColorDataVectorEntry.set(0, applicationPreferenceModel.getAlternatingColorBackgroundColor());
      alternatingColorDataVectorEntry.set(1, applicationPreferenceModel.getAlternatingColorForegroundColor());
  }

  public JPanel buildBypassSearchColorsPanel() {
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

    bypassSearchColorsCheckBox = new JCheckBox("Don't use a search color for matching rows");
    panel.add(bypassSearchColorsCheckBox);
    return panel;
  }

  public JPanel buildSearchAndAlternatingColorPanel() {
      JPanel panel = new JPanel();
      panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

      JLabel defineSearchColorsLabel = new JLabel("Find colors");

      panel.add(defineSearchColorsLabel);

      panel.add(Box.createHorizontalStrut(10));
      JScrollPane searchPane = new JScrollPane(searchTable);
      searchPane.setBorder(BorderFactory.createEmptyBorder());
      panel.add(searchPane);

      panel.add(Box.createHorizontalStrut(10));
      JLabel defineAlternatingColorLabel = new JLabel("Alternating colors");

      panel.add(defineAlternatingColorLabel);

      panel.add(Box.createHorizontalStrut(10));
      JScrollPane alternatingColorPane = new JScrollPane(alternatingColorTable);
      alternatingColorPane.setBorder(BorderFactory.createEmptyBorder());

      panel.add(alternatingColorPane);
      panel.setBorder(BorderFactory.createEtchedBorder());
      panel.add(Box.createHorizontalGlue());
      return panel;
  }

  public void updateColors() {
    tableModel.getDataVector().clear();
    tableModel.getDataVector().addAll(getColorizerVector());
    tableModel.fireTableDataChanged();
  }
  
  private Vector getColorizerVector() {
      Vector data = new Vector();
      Map map = colorizer.getRules();
      for (Object o1 : map.entrySet()) {
          Map.Entry entry = (Map.Entry) o1;
          //update ruleset list
          if (entry.getKey().equals(currentRuleSet)) {

              for (Object o : ((List) entry.getValue())) {
                  ColorRule rule = (ColorRule) o;
                  Vector v = new Vector();
                  v.add(rule.getExpression());
                  v.add(rule.getBackgroundColor());
                  v.add(rule.getForegroundColor());
                  data.add(v);
              }
          }
      }
      return data;
  }

  private void configureTable() {
    table.setToolTipText("Double click to edit");
    table.setRowHeight(20);
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    table.setColumnSelectionAllowed(false);

    Vector backgroundColors = colorizer.getDefaultColors();
    Vector foregroundColors = colorizer.getDefaultColors();
    backgroundColors.add("Browse...");
    foregroundColors.add("Browse...");

    JComboBox background = new JComboBox(backgroundColors);
    background.setMaximumRowCount(15);
    background.setRenderer(new ColorListCellRenderer());

    JComboBox foreground = new JComboBox(foregroundColors);
    foreground.setMaximumRowCount(15);
    foreground.setRenderer(new ColorListCellRenderer());

    DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
    DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
    JTextField textField = new JTextField();
    textField.addKeyListener(
      new ExpressionRuleContext(filterModel, textField));
    table.getColumnModel().getColumn(0).setCellEditor(
      new DefaultCellEditor(textField));
    table.getColumnModel().getColumn(1).setCellEditor(backgroundEditor);
    table.getColumnModel().getColumn(2).setCellEditor(foregroundEditor);

    background.addItemListener(new ColorItemListener(background));
    foreground.addItemListener(new ColorItemListener(foreground));

    table.getColumnModel().getColumn(0).setCellRenderer(
      new ExpressionTableCellRenderer());
    table.getColumnModel().getColumn(1).setCellRenderer(
      new ColorTableCellRenderer());
    table.getColumnModel().getColumn(2).setCellRenderer(
      new ColorTableCellRenderer());
  }

  private void configureSingleEntryColorTable(JTable thisTable) {
      thisTable.setToolTipText("Double click to edit");
      thisTable.setRowHeight(20);
      thisTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      thisTable.setColumnSelectionAllowed(false);

      Vector backgroundColors = colorizer.getDefaultColors();
      Vector foregroundColors = colorizer.getDefaultColors();
      backgroundColors.add("Browse...");
      foregroundColors.add("Browse...");

      JComboBox background = new JComboBox(backgroundColors);
      background.setMaximumRowCount(15);
      background.setRenderer(new ColorListCellRenderer());

      JComboBox foreground = new JComboBox(foregroundColors);
      foreground.setMaximumRowCount(15);
      foreground.setRenderer(new ColorListCellRenderer());

      DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
      DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
      thisTable.getColumnModel().getColumn(0).setCellEditor(backgroundEditor);
      thisTable.getColumnModel().getColumn(1).setCellEditor(foregroundEditor);

      background.addItemListener(new ColorItemListener(background));
      foreground.addItemListener(new ColorItemListener(foreground));

      thisTable.getColumnModel().getColumn(0).setCellRenderer(
        new ColorTableCellRenderer());
      thisTable.getColumnModel().getColumn(1).setCellRenderer(
        new ColorTableCellRenderer());
  }

  public void setCloseActionListener(ActionListener listener) {
    closeListener = listener;
  }

  public void hidePanel() {
    if (closeListener != null) {
      closeListener.actionPerformed(null);
    }
  }

  void applyRules(String ruleSet, RuleColorizer applyingColorizer) {
    table.getColumnModel().getColumn(0).getCellEditor().stopCellEditing();

    List list = new ArrayList();
    Vector vector = tableModel.getDataVector();
    StringBuilder result = new StringBuilder();

    for (int i = 0; i < vector.size(); i++) {
      Vector v = (Vector) vector.elementAt(i);

      try {
        Rule expressionRule = ExpressionRule.getRule((String) v.elementAt(0));
        Color background = getBackground();
        Color foreground = getForeground();

        if (v.elementAt(1) instanceof Color) {
          background = (Color) v.elementAt(1);
        }

        if (v.elementAt(2) instanceof Color) {
          foreground = (Color) v.elementAt(2);
        }

        ColorRule r = new ColorRule((String)v.elementAt(0), expressionRule, background, foreground);
        list.add(r);
      } catch (IllegalArgumentException iae) {
        if (!result.toString().equals("")) {
          result.append("<br>");
        }

        result.append(iae.getMessage());
      }
    }

    //all rules are valid, they can be applied
    if (result.toString().equals("")) {
      ((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
      .setToolTipText("Double click to edit");
      statusBar.setText(DEFAULT_STATUS);

      //only update rules if there were no errors
      Map map = new HashMap();
      map.put(ruleSet, list);
      applyingColorizer.setRules(map);

    } else {
      statusBar.setText("Errors - see expression tooltip (color filters won't be active until errors are resolved)");
      ((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
      .setToolTipText("<html>" + result.toString() + "</html>");
    }
  }

  JPanel buildClosePanel() {
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    panel.add(Box.createHorizontalGlue());

    JButton saveAsDefaultButton = new JButton(" Save as default ");

    saveAsDefaultButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          RuleColorizer defaultColorizer = (RuleColorizer) allLogPanelColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
          applyRules(currentRuleSet, defaultColorizer);
        }
    });

    panel.add(saveAsDefaultButton);

    JButton applyButton = new JButton(" Apply ");

    applyButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          applyRules(currentRuleSet, colorizer);
          saveSearchColors();
          saveAlternatingColors();
          saveBypassFlag();
        }
      });

    panel.add(Box.createHorizontalStrut(10));
    panel.add(applyButton);

    JButton closeButton = new JButton(" Close ");

    closeButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          hidePanel();
        }
      });
    panel.add(Box.createHorizontalStrut(10));
    panel.add(closeButton);

    return panel;
  }

  private void saveSearchColors() {
      Vector thisVector = (Vector) searchTableModel.getDataVector().get(0);
      applicationPreferenceModel.setSearchBackgroundColor((Color)thisVector.get(0));
      applicationPreferenceModel.setSearchForegroundColor((Color)thisVector.get(1));
  }

  private void saveAlternatingColors() {
      Vector thisVector = (Vector) alternatingColorTableModel.getDataVector().get(0);
      applicationPreferenceModel.setAlternatingBackgroundColor((Color)thisVector.get(0));
      Color alternatingColorForegroundColor = (Color) thisVector.get(1);
      applicationPreferenceModel.setAlternatingForegroundColor(alternatingColorForegroundColor);
  }

  private void saveBypassFlag() {
    applicationPreferenceModel.setBypassSearchColors(bypassSearchColorsCheckBox.isSelected());
  }

  JPanel buildUpDownPanel() {
    JPanel panel = new JPanel(new BorderLayout());
    JPanel innerPanel = new JPanel();
    innerPanel.setLayout(new GridLayout(5, 1));

    final JButton upButton = new JButton(ChainsawIcons.ICON_UP);
    upButton.setToolTipText("Move selected rule up");

    final JButton downButton = new JButton(ChainsawIcons.ICON_DOWN);
    downButton.setToolTipText("Move selected rule down");
    upButton.setEnabled(false);
    downButton.setEnabled(false);

    table.getSelectionModel().addListSelectionListener(
            e -> {
              if (!e.getValueIsAdjusting()) {
                int index = table.getSelectionModel().getMaxSelectionIndex();

                if (index < 0) {
                  downButton.setEnabled(false);
                  upButton.setEnabled(false);
                } else if ((index == 0) && (tableModel.getRowCount() == 1)) {
                  downButton.setEnabled(false);
                  upButton.setEnabled(false);
                } else if ((index == 0) && (tableModel.getRowCount() > 1)) {
                  downButton.setEnabled(true);
                  upButton.setEnabled(false);
                } else if (index == (tableModel.getRowCount() - 1)) {
                  downButton.setEnabled(false);
                  upButton.setEnabled(true);
                } else {
                  downButton.setEnabled(true);
                  upButton.setEnabled(true);
                }
              }
            });

    JPanel upPanel = new JPanel();

    upPanel.add(upButton);

    JPanel downPanel = new JPanel();
    downPanel.add(downButton);

    innerPanel.add(new JLabel(""));
    innerPanel.add(upPanel);
    innerPanel.add(new JLabel(""));
    innerPanel.add(downPanel);
    panel.add(innerPanel, BorderLayout.CENTER);

    upButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          int index = table.getSelectionModel().getMaxSelectionIndex();

          if (index > 0) {
            Vector v = tableModel.getDataVector();
            Vector row = (Vector) v.elementAt(index);
            tableModel.removeRow(index);
            index = index - 1;
            tableModel.insertRow(index, row);
            table.getSelectionModel().setSelectionInterval(index, index);
          }
        }
      });

    downButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          int index = table.getSelectionModel().getMaxSelectionIndex();

          if ((index > -1) && (index < (tableModel.getRowCount() - 1))) {
            Vector v = tableModel.getDataVector();
            Vector row = (Vector) v.elementAt(index);

            tableModel.removeRow(index);
            index = index + 1;
            tableModel.insertRow(index, row);
            table.getSelectionModel().setSelectionInterval(index, index);
          }
        }
      });

    return panel;
  }

  JPanel buildRulesPanel() {
    JPanel listPanel = new JPanel(new BorderLayout());
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    panel.add(Box.createVerticalStrut(10));

    JLabel rulesLabel = new JLabel("Rules:");

    panel.add(rulesLabel);

    JPanel buttonPanel = new JPanel(new GridLayout(0, 2));
    buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

    JPanel newPanel = new JPanel();
    JButton newButton = new JButton(" New ");
    newButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          int currentRow = table.getSelectedRow();
          Vector v = new Vector();
          v.add("");
          v.add(Color.white);
          v.add(Color.black);

          if (currentRow < 0) {
            tableModel.addRow(v);
            currentRow = table.getRowCount() - 1;
          } else {
            tableModel.insertRow(currentRow, v);
          }

          table.getSelectionModel().setSelectionInterval(
            currentRow, currentRow);
        }
      });

    newPanel.add(newButton);

    JPanel deletePanel = new JPanel();
    final JButton deleteButton = new JButton(" Delete ");
    deleteButton.setEnabled(false);

    deleteButton.addActionListener(
      new AbstractAction() {
        public void actionPerformed(ActionEvent evt) {
          int index = table.getSelectionModel().getMaxSelectionIndex();

          if ((index > -1) && (index < table.getRowCount())) {
            tableModel.removeRow(index);

            if (index > 0) {
              index = index - 1;
            }

            if (tableModel.getRowCount() > 0) {
              table.getSelectionModel().setSelectionInterval(index, index);
            }
          }
        }
      });

    table.getSelectionModel().addListSelectionListener(
            e -> {
              if (!e.getValueIsAdjusting()) {
                int index = table.getSelectionModel().getMaxSelectionIndex();

                if (index < 0) {
                  deleteButton.setEnabled(false);
                } else {
                  deleteButton.setEnabled(true);
                }
              }
            });

    deletePanel.add(deleteButton);

    buttonPanel.add(newPanel);
    buttonPanel.add(deletePanel);

    listPanel.add(panel, BorderLayout.NORTH);

    JPanel tablePanel = new JPanel(new BorderLayout());
    tableScrollPane.setBorder(BorderFactory.createEtchedBorder());
    tablePanel.add(tableScrollPane, BorderLayout.CENTER);
    tablePanel.add(buildUpDownPanel(), BorderLayout.EAST);
    listPanel.add(tablePanel, BorderLayout.CENTER);
    listPanel.add(buttonPanel, BorderLayout.SOUTH);

    return listPanel;
  }

    class ColorListCellRenderer extends JLabel implements ListCellRenderer {
    ColorListCellRenderer() {
      setOpaque(true);
    }

    public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected,
      boolean cellHasFocus) {
      setText(" ");

      if (isSelected && (index > -1)) {
        setBorder(BorderFactory.createLineBorder(Color.black, 2));
      } else {
        setBorder(BorderFactory.createEmptyBorder());
      }

      if (value instanceof Color) {
        setBackground((Color) value);
      } else {
        setBackground(Color.white);

        if (value != null) {
          setText(value.toString());
        }
      }

      return this;
    }
  }

  class ColorItemListener implements ItemListener {
    JComboBox box;
    JDialog dialog;
    JColorChooser colorChooser;
    Color lastColor;

    ColorItemListener(final JComboBox box) {
      this.box = box;
      colorChooser = new JColorChooser();
      dialog =
        JColorChooser.createDialog(
          box, "Pick a Color", true, //modal
          colorChooser,
                e -> {
                  box.insertItemAt(colorChooser.getColor(), 0);
                  box.setSelectedIndex(0);
                }, //OK button handler
                e -> box.setSelectedItem(lastColor)); //CANCEL button handler
      dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    }

    public void itemStateChanged(ItemEvent e) {
      if (e.getStateChange() == ItemEvent.SELECTED) {
        if (box.getSelectedItem() instanceof Color) {
          box.setBackground((Color) box.getSelectedItem());
          repaint();
        } else {
          box.setBackground(Color.white);
          int selectedRow = table.getSelectedRow();
          int selectedColumn = table.getSelectedColumn();
          if (selectedRow != -1 && selectedColumn != -1) {
              colorChooser.setColor((Color)table.getValueAt(selectedRow, selectedColumn));
              lastColor = (Color)table.getValueAt(selectedRow, selectedColumn);
          }
          dialog.setVisible(true);
        }
      }
    }
  }

  class ColorTableCellRenderer implements TableCellRenderer {
    Border border;
    JPanel panel;
    
    ColorTableCellRenderer() {
        panel = new JPanel();
        panel.setOpaque(true);
    }

    public Color getCurrentColor() {
        return panel.getBackground();
    }

    public Component getTableCellRendererComponent(
      JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
      int column) {
      if (value instanceof Color) {
        panel.setBackground((Color) value);
      }
      if (border == null) {
        border = BorderFactory.createMatteBorder(2, 2, 2, 2, table.getBackground());
      }

      panel.setBorder(border);

      return panel;
    }
  }

  class ExpressionTableCellRenderer implements TableCellRenderer {
    JPanel panel = new JPanel();
    JLabel expressionLabel = new JLabel();
    JLabel iconLabel = new JLabel();
    Icon selectedIcon = new SelectedIcon(true);
    Icon unselectedIcon = new SelectedIcon(false);

    ExpressionTableCellRenderer() {
      panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
      panel.setOpaque(true);
      panel.add(iconLabel);
      panel.add(Box.createHorizontalStrut(5));
      panel.add(expressionLabel);
    }
    
    void setToolTipText(String text) {
        panel.setToolTipText(text);
    }

    public Component getTableCellRendererComponent(
      JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
      int column) {
      if (value == null) {
          return panel;
      }

      Vector v = tableModel.getDataVector();
      Vector r = (Vector) v.elementAt(row);
      expressionLabel.setText(value.toString());

      if (r.elementAt(1) instanceof Color) {
        expressionLabel.setBackground((Color) r.elementAt(1));
        panel.setBackground((Color) r.elementAt(1));
      }

      if (r.elementAt(2) instanceof Color) {
        expressionLabel.setForeground((Color) r.elementAt(2));
        panel.setForeground((Color) r.elementAt(2));
      }

      if (isSelected) {
          iconLabel.setIcon(selectedIcon);
      } else {
          iconLabel.setIcon(unselectedIcon);
      }

      return panel;
    }
  }

  class SelectedIcon implements Icon {
      private boolean isSelected;
      private int width = 9;
      private int height = 18;
      private int[] xPoints = new int[4];
      private int[] yPoints = new int[4];

      public SelectedIcon(boolean isSelected) {
        this.isSelected = isSelected;
        xPoints[0] = 0;
        yPoints[0] = -1;
        xPoints[1] = 0;
        yPoints[1] = height;
        xPoints[2] = width;
        yPoints[2] = height / 2;
        xPoints[3] = width;
        yPoints[3] = (height / 2) - 1;
      }

      public int getIconHeight() {
        return height;
      }

      public int getIconWidth() {
        return width;
      }

      public void paintIcon(Component c, Graphics g, int x, int y) {
        if (isSelected) {
          int length = xPoints.length;
          int[] newXPoints = new int[length];
          int[] newYPoints = new int[length];

          for (int i = 0; i < length; i++) {
            newXPoints[i] = xPoints[i] + x;
            newYPoints[i] = yPoints[i] + y;
          }

          g.setColor(Color.black);

          g.fillPolygon(newXPoints, newYPoints, length);
        }
      }
  }
}
