package com.karateca;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.components.JBList;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.List;

/**
 * @author Andres Dominguez.
 */
public class JasmineDescribeReplaceAction extends AnAction {

  protected Project project;
  protected EditorImpl editor;
  protected VirtualFile virtualFile;
  protected DocumentImpl document;
  private JasmineFinder jasmineFinder;

  @Override
  public void update(AnActionEvent e) {
    e.getPresentation().setEnabled(e.getData(PlatformDataKeys.EDITOR) != null);
  }

  public void actionPerformed(AnActionEvent actionEvent) {
    project = actionEvent.getData(PlatformDataKeys.PROJECT);
    editor = (EditorImpl) actionEvent.getData(PlatformDataKeys.EDITOR);
    virtualFile = actionEvent.getData(PlatformDataKeys.VIRTUAL_FILE);
    document = (DocumentImpl) editor.getDocument();

    jasmineFinder = new JasmineFinder(project, document, editor, virtualFile);

    // Async callback to get the search results for it( and describe(
    jasmineFinder.addResultsReadyListener(new ChangeListener() {
      @Override
      public void stateChanged(ChangeEvent changeEvent) {
        if (changeEvent.getSource().equals("LinesFound")) {
          showDialog(jasmineFinder.getHierarchy());
        }
      }
    });
    jasmineFinder.findText("iit\\(|ddescribe\\(|it\\(|describe\\(", true);
  }

  private void showDialog(final List<LineFindResult> hierarchy) {
    final JBList jbList = new JBList(hierarchy.toArray());

    // Open a pop-up to select which describe or it you want to change.
    JBPopupFactory.getInstance()
            .createListPopupBuilder(jbList)
            .setTitle("Select the test or suite to add / remove")
            .setItemChoosenCallback(new Runnable() {
              public void run() {
                processSelectedLine(jbList, hierarchy);
              }
            })
            .createPopup().
            showCenteredInCurrentWindow(project);
  }

  private void processSelectedLine(final JBList theList, final List<LineFindResult> hierarchy) {

    CommandProcessor.getInstance().executeCommand(project, new Runnable() {
      @Override
      public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          @Override
          public void run() {
            int selectedIndex = theList.getSelectedIndex();
            LineFindResult lineFindResult = hierarchy.get(selectedIndex);
            changeSelectedLine(lineFindResult);
          }
        });
      }
    }, null, null);
  }

  private void changeSelectedLine(LineFindResult lineFindResult) {
    int start = lineFindResult.getStartOffset();
    int end = lineFindResult.getEndOffset();
    String newText = "";
    boolean markedForRun = lineFindResult.isMarkedForRun();

    if (lineFindResult.isDescribe()) {
      newText = markedForRun ? "describe(" : "ddescribe(";
    } else {
      newText = markedForRun ? "it(" : "iit(";
    }

    document.replaceString(start, end, newText);
  }
}

@@ -2096,14 +2096,18 @@
 ribe
+()
  or it
+()
  you
@@ -2571,23 +2571,25 @@
  JBList 
-theList
+listItems
 , final 
@@ -2622,16 +2622,133 @@
 rchy) %7B%0A
+    // Change the contents of the selected line. Wrap the call in a%0A    // command and write actions to support undo.
 %0A    Com
@@ -3020,15 +3020,17 @@
 x = 
-theList
+listItems
 .get
@@ -3062,53 +3062,68 @@
     
-LineFindResult lineFindResult = hierarchy.get
+// It returns -1 when no matches were found.%0A            if 
 (sel
@@ -3132,19 +3132,28 @@
 tedIndex
-);%0A
+ != -1) %7B%0A  
         
@@ -3179,24 +3179,52 @@
 ine(
-lineFindResult);
+hierarchy.get(selectedIndex));%0A            %7D
 %0A   
@@ -3259,20 +3259,33 @@
 %0A    %7D, 
-null
+%22Change describe%22
 , null);

check for empty search results