package jetbrains.mps.lang.test.pluginSolution.plugin;

/*Generated by MPS */

import com.intellij.openapi.ui.DialogWrapper;
import java.util.function.Function;
import javax.swing.JLabel;
import com.intellij.openapi.project.Project;
import java.util.List;
import com.intellij.ui.components.JBLabel;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import org.jetbrains.annotations.Nullable;
import javax.swing.JComponent;
import com.intellij.ui.components.JBList;
import com.intellij.ui.SimpleListCellRenderer;
import javax.swing.ListSelectionModel;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.AnActionButton;

/*package*/ class ReorderElementsDialog<E> extends DialogWrapper {
  private final LM<E> myDataModel;
  private final Function<E, String> myGetElementText;
  private final JLabel myNorthLabel;

  /*package*/ ReorderElementsDialog(Project ideaProject, List<E> elements, Function<E, String> getText) {
    super(ideaProject);
    myDataModel = new LM<>(elements);
    myGetElementText = getText;

    myNorthLabel = new JBLabel("");
    myNorthLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
    init();
    setOKActionEnabled(false);
  }

  public void setNorthPanelIcon(Icon icon) {
    myNorthLabel.setIcon(icon);
  }
  public void setNorthPanelText(String text) {
    myNorthLabel.setText(text);
  }

  @Nullable
  @Override
  protected JComponent createNorthPanel() {
    return myNorthLabel;
  }

  @Nullable
  @Override
  protected JComponent createCenterPanel() {
    final JBList<E> list = new JBList<E>(myDataModel);
    list.setCellRenderer(SimpleListCellRenderer.create("<empty>", myGetElementText::apply));
    list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    int minSelectionIndex = list.getMinSelectionIndex();
    list.scrollRectToVisible(list.getCellBounds(minSelectionIndex, minSelectionIndex));
    ToolbarDecorator decorator = ToolbarDecorator.createDecorator(list);
    decorator.setAddAction(null);
    decorator.setRemoveAction(null);
    decorator.setMoveDownActionName("Move Down");
    decorator.setMoveDownAction(new AnActionButtonRunnable() {
      @Override
      public void run(AnActionButton b) {
        // assume there's at least 1 element selected and it's not the last one (button is disabled when
        // last element is in selection, and we shall not get here)
        final ListSelectionModel selectionModel = list.getSelectionModel();
        int[] selectedIndices = selectionModel.getSelectedIndices();
        for (int i = selectedIndices.length - 1; i >= 0; i--) {
          myDataModel.moveDown(selectedIndices[i]);
        }
        selectionModel.clearSelection();
        int pos = selectedIndices.length;
        while (pos > 0) {
          int index2 = selectedIndices[--pos];
          int index1 = index2;
          while (pos > 0 && selectedIndices[pos - 1] == index1 - 1) {
            index1 = selectedIndices[--pos];
          }
          selectionModel.addSelectionInterval(index1 + 1, index2 + 1);
        }
        setOKActionEnabled(myDataModel.isOrderChanged());
      }
    });
    decorator.setMoveUpActionName("Mode Up");
    decorator.setMoveUpAction(new AnActionButtonRunnable() {
      @Override
      public void run(AnActionButton b) {
        final ListSelectionModel selectionModel = list.getSelectionModel();
        int[] selectedIndices = selectionModel.getSelectedIndices();
        for (int x : selectedIndices) {
          myDataModel.moveUp(x);
        }
        selectionModel.clearSelection();
        int pos = 0;
        while (pos < selectedIndices.length) {
          int index1 = selectedIndices[pos++];
          int index2 = index1;
          while (pos < selectedIndices.length && selectedIndices[pos] == index1 + 1) {
            index2 = selectedIndices[pos++];
          }
          selectionModel.addSelectionInterval(index1 - 1, index2 - 1);
        }
        setOKActionEnabled(myDataModel.isOrderChanged());
      }
    });
    return decorator.createPanel();
  }

  public List<E> getResult() {
    return myDataModel.toOrder();
  }
}
