package com.intellij.ui;

import com.intellij.ui.components.JBList;
import com.intellij.util.Function;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.Map;

/**
 * @author oleg
 */
public class CheckBoxList<T> extends JBList {
  private static final int DEFAULT_CHECK_BOX_WIDTH = 20;
  private CheckBoxListListener checkBoxListListener;
  private final BidirectionalMap<T, JCheckBox> myItemMap = new BidirectionalMap<T, JCheckBox>();

  public CheckBoxList(final CheckBoxListListener checkBoxListListener) {
    this(new DefaultListModel(), checkBoxListListener);
  }
  public CheckBoxList(final DefaultListModel dataModel, final CheckBoxListListener checkBoxListListener) {
    this(dataModel);
    setCheckBoxListListener(checkBoxListListener);
  }

  public CheckBoxList() {
    this(new DefaultListModel());
  }

  public CheckBoxList(final DefaultListModel dataModel) {
    super();
    //noinspection unchecked
    setModel(dataModel);
    setCellRenderer(new CellRenderer());
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    setBorder(BorderFactory.createEtchedBorder());
    addKeyListener(new KeyAdapter() {
      @Override
      public void keyTyped(KeyEvent e) {
        if (e.getKeyChar() == ' ') {
          for (int index : getSelectedIndices()) {
            if (index >= 0) {
              JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index);
              setSelected(checkbox, index);
            }
          }
        }
      }
    });
    new ClickListener() {
      @Override
      public boolean onClick(@NotNull MouseEvent e, int clickCount) {
        if (isEnabled()) {
          int index = locationToIndex(e.getPoint());

          if (index != -1) {
            JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index);
            int iconArea;
            try {
              iconArea = checkbox.getMargin().left +
                         ((BasicRadioButtonUI)checkbox.getUI()).getDefaultIcon().getIconWidth() +
                         checkbox.getIconTextGap();
            }
            catch (ClassCastException c) {
              iconArea = DEFAULT_CHECK_BOX_WIDTH;
            }
            if (e.getX() < iconArea) {
              setSelected(checkbox, index);
              return true;
            }
          }
        }
        return false;
      }
    }.installOn(this);
  }

  public void setStringItems(final Map<String, Boolean> items) {
    clear();
    for (Map.Entry<String, Boolean> entry : items.entrySet()) {
      //noinspection unchecked
      addItem((T)entry.getKey(), entry.getKey(), entry.getValue());
    }
  }

  public void setItems(final List<T> items, @Nullable Function<T, String> converter) {
    clear();
    for (T item : items) {
      String text = converter != null ? converter.fun(item) : item.toString();
      addItem(item, text, false);
    }
  }

  public void addItem(T item, String text, boolean selected) {
    JCheckBox checkBox = new JCheckBox(text, selected);
    myItemMap.put(item, checkBox);
    //noinspection unchecked
    ((DefaultListModel) getModel()).addElement(checkBox);
  }

  public void updateItem(@NotNull T oldItem, @NotNull T newItem) {
    JCheckBox checkBox = myItemMap.remove(oldItem);
    myItemMap.put(newItem, checkBox);
  }

  @Nullable
  public T getItemAt(int index) {
    JCheckBox checkBox = (JCheckBox)getModel().getElementAt(index);
    List<T> value = myItemMap.getKeysByValue(checkBox);
    return value == null || value.isEmpty() ? null : value.get(0);
  }

  public void clear() {
    ((DefaultListModel) getModel()).clear();
    myItemMap.clear();
  }

  public boolean isItemSelected(int index) {
    return ((JCheckBox)getModel().getElementAt(index)).isSelected();  
  }

  public boolean isItemSelected(T item) {
    JCheckBox checkBox = myItemMap.get(item);
    return checkBox != null && checkBox.isSelected();
  }

  public void setItemSelected(T item, boolean selected) {
    JCheckBox checkBox = myItemMap.get(item);
    if (checkBox != null) {
      checkBox.setSelected(selected);
    }
  }

  private void setSelected(JCheckBox checkbox, int index) {
    boolean value = !checkbox.isSelected();
    checkbox.setSelected(value);
    repaint();

    // fire change notification in case if we've already initialized model
    final ListModel model = getModel();
    if (model instanceof DefaultListModel) {
      //noinspection unchecked
      ((DefaultListModel)model).setElementAt(getModel().getElementAt(index), index);
    }

    if (checkBoxListListener != null) {
      checkBoxListListener.checkBoxSelectionChanged(index, value);
    }
  }

  public void setCheckBoxListListener(CheckBoxListListener checkBoxListListener) {
    this.checkBoxListListener = checkBoxListListener;
  }

  protected void adjustRendering(final JCheckBox checkBox, final boolean selected, final boolean hasFocus) {
  }

  private class CellRenderer implements ListCellRenderer {
    private final Border mySelectedBorder;
    private final Border myBorder;

    private CellRenderer() {
      mySelectedBorder = UIManager.getBorder("List.focusCellHighlightBorder");
      final Insets borderInsets = mySelectedBorder.getBorderInsets(new JCheckBox());
      myBorder = new EmptyBorder(borderInsets);
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      JCheckBox checkbox = (JCheckBox)value;
      if (!UIUtil.isUnderNimbusLookAndFeel()) {
        checkbox.setBackground(getBackground(isSelected, checkbox));
        checkbox.setForeground(getForeground(isSelected, checkbox));
      }
      checkbox.setEnabled(isEnabled());
      checkbox.setFont(getFont(checkbox));
      checkbox.setFocusPainted(false);
      checkbox.setBorderPainted(true);
      checkbox.setBorder(isSelected ? mySelectedBorder : myBorder);
      adjustRendering(checkbox, isSelected, cellHasFocus);
      return checkbox;
    }
  }

  protected Font getFont(final JCheckBox checkbox) {
    return getFont();
  }

  protected Color getBackground(final boolean isSelected, final JCheckBox checkbox) {
      return isSelected ? getSelectionBackground() : getBackground();
    }

  protected Color getForeground(final boolean isSelected, final JCheckBox checkbox) {
    return isSelected ? getSelectionForeground() : getForeground();
  }
}
