package com.karateca.ddescriber;

import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.find.FindResult;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EventDispatcher;

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

/**
 * Used to find suites and unit tests in a JsUnit JavaScript file.
 */
class JasmineFinder {

  private final Project project;
  private final DocumentImpl document;
  private final EditorImpl editor;
  private final VirtualFile virtualFile;
  private FindManager findManager;
  private FindModel findModel;
  private List<LineFindResult> lineFindResults;

  private final EventDispatcher<ChangeListener> myEventDispatcher = EventDispatcher.create(ChangeListener.class);

  public JasmineFinder(Project project, DocumentImpl document, EditorImpl editor, VirtualFile virtualFile) {
    this.project = project;
    this.document = document;
    this.editor = editor;
    this.virtualFile = virtualFile;
  }

  FindModel createFindModel(FindManager findManager) {
    FindModel clone = (FindModel) findManager.getFindInFileModel().clone();
    clone.setFindAll(true);
    clone.setFromCursor(true);
    clone.setForward(false);
    clone.setWholeWordsOnly(false);
    clone.setCaseSensitive(true);
    clone.setSearchHighlighters(true);
    clone.setPreserveCase(false);

    return clone;
  }

  public void findText(final String text, boolean isRegEx) {
    findManager = FindManager.getInstance(project);
    findModel = createFindModel(findManager);

    findModel.setStringToFind(text);
    findModel.setRegularExpressions(isRegEx);

    ApplicationManager.getApplication().runReadAction(new Runnable() {
      @Override
      public void run() {
        findAll();
        myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent("LinesFound"));
      }
    });
  }

  private void findAll() {
    lineFindResults = new ArrayList<LineFindResult>();
    CharSequence text = document.getCharsSequence();
    int offset = editor.getCaretModel().getOffset();

    while (true) {
      FindResult result = findManager.findString(text, offset, findModel, virtualFile);

      if (!result.isStringFound()) {
        return;
      }

      offset = result.getStartOffset();
      lineFindResults.add(new LineFindResult(document, result));
    }
  }


  /**
   * Get the search results in the form a a hierarchy starting from the current
   * scope, then going to the parents all the way to the top. The hierarchy is
   * calculated with the indentation of the describe() or the it().
   * @return The current test of suite and the parents.
   */
  public List<LineFindResult> getHierarchy() {
    // Filter the hierarchy.
    int currentIndentation = Integer.MAX_VALUE;
    List<LineFindResult> hierarchy = new ArrayList<LineFindResult>();

    // Find all the parents from the current scope.
    for (LineFindResult line : lineFindResults) {
      if (line.getIndentation() < currentIndentation) {
        currentIndentation = line.getIndentation();
        hierarchy.add(line);
      }
    }
    return hierarchy;
  }

  /**
   * Register for change events.
   * @param changeListener The listener to be added.
   */
  public void addResultsReadyListener(ChangeListener changeListener) {
    myEventDispatcher.addListener(changeListener);
  }
}

@@ -2624,17 +2624,16 @@
  %7D%0A  %7D%0A%0A
-%0A
   /**%0A  

remove empty line