/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed 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 com.intellij.ui.components;

import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ListUtil;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.Map;

/**
 * A UI control which consists of two lists with ability to move elements between them.
 * <p/>
 * It looks as <a href="http://openfaces.org/documentation/developersGuide/twolistselection.html">here</a>.
 * 
 * @author Konstantin Bulenkov
 */
public class JBMovePanel extends JBPanel {

  public static final String MOVE_PANEL_PLACE = "MOVE_PANEL";

  public static final InsertPositionStrategy ANCHORING_SELECTION = new InsertPositionStrategy() {
    @Override
    public int getInsertionIndex(@NotNull Object data, @NotNull JList list) {
      int index = list.getSelectedIndex();
      DefaultListModel model = (DefaultListModel)list.getModel();
      return index < 0 ? model.getSize() : index + 1;
    }
  };

  public static final InsertPositionStrategy NATURAL_ORDER = new InsertPositionStrategy() {
    @SuppressWarnings("unchecked")
    @Override
    public int getInsertionIndex(@NotNull Object data, @NotNull JList list) {
      Enumeration elements = ((DefaultListModel)list.getModel()).elements();
      int index = 0;
      while (elements.hasMoreElements()) {
        Object e = elements.nextElement();
        // DefaultListModel is type-aware only since java7, so, use raw types until we're on java6.
        if (((Comparable)e).compareTo(data) >= 0) {
          break;
        }
        index++;
      }
      return index;
    }
  };

  @NotNull private final Map<ButtonType, ActionButton> myButtons = new EnumMap<ButtonType, ActionButton>(ButtonType.class);

  @NotNull private final ListPanel myLeftPanel  = new ListPanel();
  @NotNull private final ListPanel myRightPanel = new ListPanel();

  @NotNull protected final JList        myLeftList;
  @NotNull protected final JList        myRightList;
  @NotNull protected final ActionButton myLeftButton;
  @NotNull protected final ActionButton myAllLeftButton;
  @NotNull protected final ActionButton myRightButton;
  @NotNull protected final ActionButton myAllRightButton;
  @NotNull protected final ActionButton myUpButton;
  @NotNull protected final ActionButton myDownButton;

  @NotNull private InsertPositionStrategy myLeftInsertionStrategy = ANCHORING_SELECTION;
  @NotNull private InsertPositionStrategy myRightInsertionStrategy = ANCHORING_SELECTION;

  private boolean myActivePreferredSizeProcessing;

  public enum ButtonType {LEFT, RIGHT, ALL_LEFT, ALL_RIGHT}

  public JBMovePanel(@NotNull JList left, @NotNull JList right) {
    super(new GridBagLayout());
    assertModelIsEditable(left);
    assertModelIsEditable(right);
    myLeftList = left;
    myRightList = right;

    final JPanel leftRightButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
    leftRightButtonsPanel.add(myRightButton = createButton(ButtonType.RIGHT));
    leftRightButtonsPanel.add(myAllRightButton = createButton(ButtonType.ALL_RIGHT));
    leftRightButtonsPanel.add(myLeftButton = createButton(ButtonType.LEFT));
    leftRightButtonsPanel.add(myAllLeftButton = createButton(ButtonType.ALL_LEFT));

    myUpButton = createButton(new UpAction());
    myDownButton = createButton(new DownAction());
    final JPanel upDownButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
    upDownButtonsPanel.add(myUpButton);
    upDownButtonsPanel.add(myDownButton);

    MouseListener mouseListener = new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() != 2 || e.getButton() != MouseEvent.BUTTON1) {
          return;
        }
        if (e.getSource() == myLeftList) {
          doRight();
        }
        else if (e.getSource() == myRightList) {
          doLeft();
        }
      }
    };
    myLeftList.addMouseListener(mouseListener);
    myRightList.addMouseListener(mouseListener);

    GridBag listConstraints = new GridBag().weightx(1).weighty(1).fillCell();
    GridBag buttonConstraints = new GridBag().anchor(GridBagConstraints.CENTER);
    myLeftPanel.add(ScrollPaneFactory.createScrollPane(left), listConstraints);
    add(myLeftPanel, listConstraints);
    add(leftRightButtonsPanel, buttonConstraints);
    myRightPanel.add(ScrollPaneFactory.createScrollPane(right), listConstraints);
    add(myRightPanel, listConstraints);
    add(upDownButtonsPanel, buttonConstraints);
  }

  private static void assertModelIsEditable(@NotNull JList list) {
    assert list.getModel() instanceof DefaultListModel : String
      .format("List model should extends %s interface", DefaultListModel.class.getName());
  }

  public void setShowButtons(@NotNull ButtonType... types) {
    for (ActionButton button : myButtons.values()) {
      button.setVisible(false);
    }
    for (ButtonType type : types) {
      myButtons.get(type).setVisible(true);
    }
  }

  public void setListLabels(@NotNull String left, @NotNull String right) {
    // Border insets are used as a component insets (see JComponent.getInsets()). That's why an ugly bottom inset is used when
    // we create a border with default insets. That is the reason why we explicitly specify bottom inset as zero.
    Insets insets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET,
                               IdeBorderFactory.TITLED_BORDER_LEFT_INSET,
                               0,
                               IdeBorderFactory.TITLED_BORDER_RIGHT_INSET);
    myLeftPanel.setBorder(IdeBorderFactory.createTitledBorder(left, false, insets));
    myRightPanel.setBorder(IdeBorderFactory.createTitledBorder(right, false, insets));
  }

  public void setLeftInsertionStrategy(@NotNull InsertPositionStrategy leftInsertionStrategy) {
    myLeftInsertionStrategy = leftInsertionStrategy;
  }
  
  // Commented to preserve green code policy until this method is not used. Uncomment when necessary.
  //public void setRightInsertionStrategy(@NotNull InsertPositionStrategy rightInsertionStrategy) {
  //  myRightInsertionStrategy = rightInsertionStrategy;
  //}
  
  @Override
  public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    myLeftList.setEnabled(enabled);
    myRightList.setEnabled(enabled);
    for (ActionButton button : myButtons.values()) {
      button.setEnabled(enabled);
    }
  }

  @NotNull
  private ActionButton createButton(@NotNull final ButtonType type) {
    final AnAction action;
    switch (type) {
      case LEFT:
        action = new LeftAction();
        break;
      case RIGHT:
        action = new RightAction();
        break;
      case ALL_LEFT:
        action = new AllLeftAction();
        break;
      case ALL_RIGHT:
        action = new AllRightAction();
        break;
      default: throw new IllegalArgumentException("Unsupported button type: " + type);
    }


    ActionButton button = createButton(action);
    myButtons.put(type, button);
    return button;
  }

  @NotNull
  private static ActionButton createButton(@NotNull final AnAction action) {
    PresentationFactory presentationFactory = new PresentationFactory();
    Icon icon = AllIcons.Actions.AllLeft;
    Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight());
    return new ActionButton(action, presentationFactory.getPresentation(action), MOVE_PANEL_PLACE, size);
  }

  protected void doRight() {
    moveBetween(myRightList, myRightInsertionStrategy, myLeftList);
  }

  protected void doLeft() {
    moveBetween(myLeftList, myLeftInsertionStrategy, myRightList);
  }

  protected void doAllLeft() {
    moveAllBetween(myLeftList, myRightList);
  }

  protected void doAllRight() {
    moveAllBetween(myRightList, myLeftList);
  }

  private static void moveBetween(@NotNull JList to, @NotNull InsertPositionStrategy strategy, @NotNull JList from) {
    final int[] indices = from.getSelectedIndices();
    if (indices.length <= 0) {
      return;
    }
    
    final Object[] values = from.getSelectedValues();
    for (int i = indices.length - 1; i >= 0; i--) {
      ((DefaultListModel)from.getModel()).remove(indices[i]);
    }
    if (from.getModel().getSize() > 0) {
      int newSelectionIndex = indices[0];
      newSelectionIndex = Math.min(from.getModel().getSize() - 1, newSelectionIndex);
      from.setSelectedIndex(newSelectionIndex);
    }

    to.clearSelection();
    DefaultListModel toModel = (DefaultListModel)to.getModel();
    int newSelectionIndex = -1;
    for (Object value : values) {
      if (!toModel.contains(value)) {
        int i = strategy.getInsertionIndex(value, to);
        if (newSelectionIndex < 0) {
          newSelectionIndex = i;
        }
        toModel.add(i, value);
        to.addSelectionInterval(i, i);
      }
    }
  }

  private static void moveAllBetween(@NotNull JList to, @NotNull JList from) {
    final DefaultListModel fromModel = (DefaultListModel)from.getModel();
    final DefaultListModel toModel = (DefaultListModel)to.getModel();
    while (fromModel.getSize() > 0) {
      Object element = fromModel.remove(0);
      if (!toModel.contains(element)) {
        toModel.addElement(element);
      }
    }
  }

  public static void main(String[] args) {
    final JBMovePanel panel = new JBMovePanel(new JBList("asdas", "weqrwe", "ads12312", "aZSD23"),
                                              new JBList("123412", "as2341", "aaaaaaaaaaa", "ZZZZZZZZZZ", "12"));
    final JFrame test = new JFrame("Test");
    test.setContentPane(panel);
    test.setSize(500, 500);
    test.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    test.setVisible(true);
  }
  
  public interface InsertPositionStrategy {
    int getInsertionIndex(@NotNull Object data, @NotNull JList list);
  }

  /**
   * The general idea is to layout target lists to use the same width. This wrapper panel controls that.
   */
  private class ListPanel extends JPanel {

    ListPanel() {
      super(new GridBagLayout());
    }

    @Override
    public Dimension getPreferredSize() {
      Dimension d1 = super.getPreferredSize();
      if (myActivePreferredSizeProcessing) {
        return d1;
      }
      myActivePreferredSizeProcessing = true;
      try {
        final Dimension d2;
        if (myLeftPanel == this) {
          d2 = myRightPanel.getPreferredSize();
        }
        else {
          d2 = myLeftPanel.getPreferredSize();
        }
        return new Dimension(Math.max(d1.width, d2.width), Math.max(d1.height, d2.height));
      }
      finally {
        myActivePreferredSizeProcessing = false;
      }
    }
  }
  
  private class LeftAction extends AnAction {

    LeftAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.Left);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      doLeft(); 
    }
  }

  private class RightAction extends AnAction {

    RightAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.Right);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      doRight();
    }
  }

  private class AllLeftAction extends AnAction {

    AllLeftAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.AllLeft);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      doAllLeft();
    }
  }

  private class AllRightAction extends AnAction {

    AllRightAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.AllRight);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      doAllRight();
    }
  }
  
  private class UpAction extends AnAction {
    
    UpAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.UP);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      ListUtil.moveSelectedItemsUp(myRightList); 
    }
  }

  private class DownAction extends AnAction {

    DownAction() {
      getTemplatePresentation().setIcon(AllIcons.Actions.Down);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      ListUtil.moveSelectedItemsDown(myRightList);
    }
  }
}
