/*
 * Copyright 2000-2014 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: max
 * Date: Jun 6, 2002
 * Time: 4:54:58 PM
 * To change template for new class use
 * Code Style | Class Templates options (Tools | IDE Options).
 */
package com.intellij.openapi.editor.actions;

import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.ide.ui.customization.CustomActionsSchema;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.ActionPopupMenu;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.event.EditorMouseListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EditorPopupHandler;
import org.jetbrains.annotations.NotNull;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.List;

public class EditorActionUtil {

  /**
   * Editor actions may be invoked multiple ways - programmatically, via keyboard/mouse shortcut, main/context menu etc.
   * Action processing may also interfere with standard editor behavior (caret position change, selection change etc).
   * <p/>
   * E.g. consider a situation when context menu is shown on right mouse click -
   * {@link EditorMouseListener#mousePressed(EditorMouseEvent) the contract says} that no common actions have been performed yet.
   * However, some actions may operate on an 'active element' (an element under caret), hence, they would incorrectly because the
   * caret position has not been changed yet.
   * <p/>
   * We address that problem by providing a special key that is intended to hold 'expected caret offset', i.e. offset where we
   * expect the caret to be located at the near future.
   */
  public static final Key<Integer> EXPECTED_CARET_OFFSET = Key.create("expectedEditorOffset");
  
  protected static final Object EDIT_COMMAND_GROUP = Key.create("EditGroup");
  public static final Object DELETE_COMMAND_GROUP = Key.create("DeleteGroup");

  private EditorActionUtil() {
  }

  /**
   * Tries to change given editor's viewport position in vertical dimension by the given number of visual lines.
   * 
   * @param editor     target editor which viewport position should be changed
   * @param lineShift  defines viewport position's vertical change length
   * @param columnShift  defines viewport position's horizontal change length
   * @param moveCaret  flag that identifies whether caret should be moved if its current position becomes off-screen
   */
  public static void scrollRelatively(@NotNull Editor editor, int lineShift, int columnShift, boolean moveCaret) {
    if (lineShift != 0) {
      editor.getScrollingModel().scrollVertically(
        editor.getScrollingModel().getVerticalScrollOffset() + lineShift * editor.getLineHeight()
      );
    }
    if (columnShift != 0) {
      editor.getScrollingModel().scrollHorizontally(
        editor.getScrollingModel().getHorizontalScrollOffset() + columnShift * EditorUtil.getSpaceWidth(Font.PLAIN, editor)
      );
    }

    if (!moveCaret) {
      return;
    }
    
    Rectangle viewRectangle = editor.getScrollingModel().getVisibleArea();
    int lineNumber = editor.getCaretModel().getVisualPosition().line;
    VisualPosition startPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y));
    int start = startPos.line + 1;
    VisualPosition endPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y + viewRectangle.height));
    int end = endPos.line - 2;
    if (lineNumber < start) {
      editor.getCaretModel().moveCaretRelatively(0, start - lineNumber, false, false, true);
    }
    else if (lineNumber > end) {
      editor.getCaretModel().moveCaretRelatively(0, end - lineNumber, false, false, true);
    }
  }

  public static void moveCaretRelativelyAndScroll(@NotNull Editor editor,
                                                  int columnShift,
                                                  int lineShift,
                                                  boolean withSelection) {
    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
    VisualPosition pos = editor.getCaretModel().getVisualPosition();
    Point caretLocation = editor.visualPositionToXY(pos);
    int caretVShift = caretLocation.y - visibleArea.y;

    editor.getCaretModel().moveCaretRelatively(columnShift, lineShift, withSelection, false, false);

    //editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    VisualPosition caretPos = editor.getCaretModel().getVisualPosition();
    Point caretLocation2 = editor.visualPositionToXY(caretPos);
    final boolean scrollToCaret = !(editor instanceof EditorImpl) || ((EditorImpl)editor).isScrollToCaret();
    if (scrollToCaret) {
      editor.getScrollingModel().scrollVertically(caretLocation2.y - caretVShift);
    }
  }

  public static void indentLine(Project project, @NotNull Editor editor, int lineNumber, int indent) {
    EditorSettings editorSettings = editor.getSettings();
    Document document = editor.getDocument();
    int spacesEnd = 0;
    int lineStart = 0;
    int tabsEnd = 0;
    if (lineNumber < document.getLineCount()) {
      lineStart = document.getLineStartOffset(lineNumber);
      int lineEnd = document.getLineEndOffset(lineNumber);
      spacesEnd = lineStart;
      CharSequence text = document.getCharsSequence();
      boolean inTabs = true;
      for (; spacesEnd <= lineEnd; spacesEnd++) {
        if (spacesEnd == lineEnd) {
          break;
        }
        char c = text.charAt(spacesEnd);
        if (c != '\t') {
          if (inTabs) {
            inTabs = false;
            tabsEnd = spacesEnd;
          }
          if (c != ' ') break;
        }
      }
      if (inTabs) {
        tabsEnd = lineEnd;
      } 
    }
    int oldLength = editor.offsetToLogicalPosition(spacesEnd).column;
    tabsEnd = editor.offsetToLogicalPosition(tabsEnd).column;

    int newLength = oldLength + indent;
    if (newLength < 0) {
      newLength = 0;
    }
    tabsEnd += indent;
    if (tabsEnd < 0) tabsEnd = 0;
    if (!shouldUseSmartTabs(project, editor)) tabsEnd = newLength;
    StringBuilder buf = new StringBuilder(newLength);
    int tabSize = editorSettings.getTabSize(project);
    for (int i = 0; i < newLength;) {
      if (tabSize > 0 && editorSettings.isUseTabCharacter(project) && i + tabSize <= tabsEnd) {
        buf.append('\t');
        i += tabSize;
      }
      else {
        buf.append(' ');
        i++;
      }
    }

    int newCaretOffset = editor.getCaretModel().getOffset();
    if (newCaretOffset >= spacesEnd) {
      newCaretOffset += buf.length() - (spacesEnd - lineStart);
    }

    if (buf.length() > 0) {
      if (spacesEnd > lineStart) {
        document.replaceString(lineStart, spacesEnd, buf.toString());
      }
      else {
        document.insertString(lineStart, buf.toString());
      }
    }
    else {
      if (spacesEnd > lineStart) {
        document.deleteString(lineStart, spacesEnd);
      }
    }

    editor.getCaretModel().moveToOffset(Math.min(document.getTextLength(), newCaretOffset));
  }

  private static boolean shouldUseSmartTabs(Project project, @NotNull Editor editor) {
    if (!(editor instanceof EditorEx)) return false;
    VirtualFile file = ((EditorEx)editor).getVirtualFile();
    FileType fileType = file == null ? null : file.getFileType();
    return fileType != null && CodeStyleFacade.getInstance(project).isSmartTabs(fileType);
  }

  public static boolean isWordStart(@NotNull CharSequence text, int offset, boolean isCamel) {
    char prev = offset > 0 ? text.charAt(offset - 1) : 0;
    char current = text.charAt(offset);

    final boolean firstIsIdentifierPart = Character.isJavaIdentifierPart(prev);
    final boolean secondIsIdentifierPart = Character.isJavaIdentifierPart(current);
    if (!firstIsIdentifierPart && secondIsIdentifierPart) {
      return true;
    }

    if (isCamel && firstIsIdentifierPart && secondIsIdentifierPart && isHumpBound(text, offset, true)) {
      return true;
    }

    return (Character.isWhitespace(prev) || firstIsIdentifierPart) &&
           !Character.isWhitespace(current) && !secondIsIdentifierPart;
  }
  
  private static boolean isLowerCaseOrDigit(char c) {
    return Character.isLowerCase(c) || Character.isDigit(c);
  }

  public static boolean isWordEnd(@NotNull CharSequence text, int offset, boolean isCamel) {
    char prev = offset > 0 ? text.charAt(offset - 1) : 0;
    char current = text.charAt(offset);
    char next = offset + 1 < text.length() ? text.charAt(offset + 1) : 0;

    final boolean firstIsIdentifierPart = Character.isJavaIdentifierPart(prev);
    final boolean secondIsIdentifierPart = Character.isJavaIdentifierPart(current);
    if (firstIsIdentifierPart && !secondIsIdentifierPart) {
      return true;
    }

    if (isCamel) {
      if (firstIsIdentifierPart
          && (Character.isLowerCase(prev) && Character.isUpperCase(current)
              || prev != '_' && current == '_'
              || Character.isUpperCase(prev) && Character.isUpperCase(current) && Character.isLowerCase(next)))
      {
        return true;
      }
    }

    return !Character.isWhitespace(prev) && !firstIsIdentifierPart &&
           (Character.isWhitespace(current) || secondIsIdentifierPart);
  }

  /**
   * Depending on the current caret position and 'smart Home' editor settings, moves caret to the start of current visual line
   * or to the first non-whitespace character on it.
   *
   * @param isWithSelection if true - sets selection from old caret position to the new one, if false - clears selection
   *
   * @see com.intellij.openapi.editor.actions.EditorActionUtil#moveCaretToLineStartIgnoringSoftWraps(com.intellij.openapi.editor.Editor)
   */
  public static void moveCaretToLineStart(@NotNull Editor editor, boolean isWithSelection) {
    Document document = editor.getDocument();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();
    EditorSettings editorSettings = editor.getSettings();

    int logCaretLine = caretModel.getLogicalPosition().line;
    VisualPosition currentVisCaret = caretModel.getVisualPosition();
    VisualPosition caretLogLineStartVis = editor.offsetToVisualPosition(document.getLineStartOffset(logCaretLine));

    if (currentVisCaret.line > caretLogLineStartVis.line) {
      // Caret is located not at the first visual line of soft-wrapped logical line.
      if (editorSettings.isSmartHome()) {
        moveCaretToStartOfSoftWrappedLine(editor, currentVisCaret, currentVisCaret.line - caretLogLineStartVis.line);
      }
      else {
        caretModel.moveToVisualPosition(new VisualPosition(currentVisCaret.line, 0));
      }
      setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
      return;
    }

    // Skip folded lines.
    int logLineToUse = logCaretLine - 1;
    while (logLineToUse >= 0 && editor.offsetToVisualPosition(document.getLineEndOffset(logLineToUse)).line == currentVisCaret.line) {
      logLineToUse--;
    }
    logLineToUse++;

    if (logLineToUse >= document.getLineCount() || !editorSettings.isSmartHome()) {
      editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logLineToUse, 0));
    }
    else if (logLineToUse == logCaretLine) {
      int line = currentVisCaret.line;
      int column;
      if (currentVisCaret.column == 0) {
        column = findSmartIndentColumn(editor, currentVisCaret.line);
      }
      else {
        column = findFirstNonSpaceColumnOnTheLine(editor, currentVisCaret.line);
        if (column >= currentVisCaret.column) {
          column = 0;
        }
      }
      caretModel.moveToVisualPosition(new VisualPosition(line, Math.max(column, 0)));
    }
    else {
      LogicalPosition logLineEndLog = editor.offsetToLogicalPosition(document.getLineEndOffset(logLineToUse));
      VisualPosition logLineEndVis = editor.logicalToVisualPosition(logLineEndLog);
      if (logLineEndLog.softWrapLinesOnCurrentLogicalLine > 0) {
        moveCaretToStartOfSoftWrappedLine(editor, logLineEndVis, logLineEndLog.softWrapLinesOnCurrentLogicalLine);
      }
      else {
        int line = logLineEndVis.line;
        if (currentVisCaret.column == 0 && editorSettings.isSmartHome()) {
          findSmartIndentColumn(editor, line);
        }
        int column = 0;
        caretModel.moveToVisualPosition(new VisualPosition(line, column));
      }
    }

    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
  }

  private static void moveCaretToStartOfSoftWrappedLine(@NotNull Editor editor, VisualPosition currentVisual, int softWrappedLines) {
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition startLineLogical = editor.visualToLogicalPosition(new VisualPosition(currentVisual.line, 0));
    int startLineOffset = editor.logicalPositionToOffset(startLineLogical);
    SoftWrapModel softWrapModel = editor.getSoftWrapModel();
    SoftWrap softWrap = softWrapModel.getSoftWrap(startLineOffset);
    if (softWrap == null) {
      // Don't expect to be here.
      int column = findFirstNonSpaceColumnOnTheLine(editor, currentVisual.line);
      int columnToMove = column;
      if (column < 0 || currentVisual.column <= column && currentVisual.column > 0) {
        columnToMove = 0;
      }
      caretModel.moveToVisualPosition(new VisualPosition(currentVisual.line, columnToMove));
      return;
    }

    if (currentVisual.column > softWrap.getIndentInColumns()) {
      caretModel.moveToOffset(softWrap.getStart());
    }
    else if (currentVisual.column > 0) {
      caretModel.moveToVisualPosition(new VisualPosition(currentVisual.line, 0));
    }
    else {
      // We assume that caret is already located at zero visual column of soft-wrapped line if control flow reaches this place.
      int newVisualCaretLine = currentVisual.line - 1;
      int newVisualCaretColumn = -1;
      if (softWrappedLines > 1) {
        int offset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(newVisualCaretLine, 0)));
        SoftWrap prevLineSoftWrap = softWrapModel.getSoftWrap(offset);
        if (prevLineSoftWrap != null) {
          newVisualCaretColumn = prevLineSoftWrap.getIndentInColumns();
        }
      }
      if (newVisualCaretColumn < 0) {
        newVisualCaretColumn = findFirstNonSpaceColumnOnTheLine(editor, newVisualCaretLine);
      }
      caretModel.moveToVisualPosition(new VisualPosition(newVisualCaretLine, newVisualCaretColumn));
    }
  }

  private static int findSmartIndentColumn(@NotNull Editor editor, int visualLine) {
    for (int i = visualLine; i >= 0; i--) {
      int column = findFirstNonSpaceColumnOnTheLine(editor, i);
      if (column >= 0) {
        return column;
      }
    }
    return 0;
  }

  /**
   * Tries to find visual column that points to the first non-white space symbol at the visual line at the given editor.
   *
   * @param editor              target editor
   * @param visualLineNumber    target visual line
   * @return                    visual column that points to the first non-white space symbol at the target visual line if the one exists;
   *                            <code>'-1'</code> otherwise
   */
  public static int findFirstNonSpaceColumnOnTheLine(@NotNull Editor editor, int visualLineNumber) {
    Document document = editor.getDocument();
    VisualPosition visLine = new VisualPosition(visualLineNumber, 0);
    int logLine = editor.visualToLogicalPosition(visLine).line;
    int logLineStartOffset = document.getLineStartOffset(logLine);
    int logLineEndOffset = document.getLineEndOffset(logLine);
    LogicalPosition logLineStart = editor.offsetToLogicalPosition(logLineStartOffset);
    VisualPosition visLineStart = editor.logicalToVisualPosition(logLineStart);

    boolean softWrapIntroducedLine = visLineStart.line != visualLineNumber;
    if (!softWrapIntroducedLine) {
      int offset = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), logLineStartOffset, logLineEndOffset);
      if (offset >= 0) {
        return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), logLineStartOffset, offset);
      }
      else {
        return -1;
      }
    }

    int lineFeedsToSkip = visualLineNumber - visLineStart.line;
    List<? extends SoftWrap> softWraps = editor.getSoftWrapModel().getSoftWrapsForLine(logLine);
    for (SoftWrap softWrap : softWraps) {
      CharSequence softWrapText = softWrap.getText();
      int softWrapLineFeedsNumber = StringUtil.countNewLines(softWrapText);

      if (softWrapLineFeedsNumber < lineFeedsToSkip) {
        lineFeedsToSkip -= softWrapLineFeedsNumber;
        continue;
      }

      // Point to the first non-white space symbol at the target soft wrap visual line or to the first non-white space symbol
      // of document line that follows it if possible.
      int softWrapTextLength = softWrapText.length();
      boolean skip = true;
      for (int j = 0; j < softWrapTextLength; j++) {
        if (softWrapText.charAt(j) == '\n') {
          skip = --lineFeedsToSkip > 0;
          continue;
        }
        if (skip) {
          continue;
        }

        int nextSoftWrapLineFeedOffset = StringUtil.indexOf(softWrapText, '\n', j, softWrapTextLength);

        int end = findFirstNonSpaceOffsetInRange(softWrapText, j, softWrapTextLength);
        if (end >= 0) {
          // Non space symbol is contained at soft wrap text after offset that corresponds to the target visual line start.
          if (nextSoftWrapLineFeedOffset < 0 || end < nextSoftWrapLineFeedOffset) {
            return EditorUtil.calcColumnNumber(editor, softWrapText, j, end);
          }
          else {
            return -1;
          }
        }

        if (nextSoftWrapLineFeedOffset >= 0) {
          // There are soft wrap-introduced visual lines after the target one
          return -1;
        }
      }
      int end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset);
      if (end >= 0) {
        return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end);
      }
      else {
        return -1;
      }
    }
    return -1;
  }

  public static int findFirstNonSpaceOffsetOnTheLine(@NotNull Document document, int lineNumber) {
    int lineStart = document.getLineStartOffset(lineNumber);
    int lineEnd = document.getLineEndOffset(lineNumber);
    int result = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), lineStart, lineEnd);
    return result >= 0 ? result : lineEnd;
  }

  /**
   * Tries to find non white space symbol at the given range at the given document.
   *
   * @param text        text to be inspected
   * @param start       target start offset (inclusive)
   * @param end         target end offset (exclusive)
   * @return            index of the first non-white space character at the given document at the given range if the one is found;
   *                    <code>'-1'</code> otherwise
   */
  public static int findFirstNonSpaceOffsetInRange(@NotNull CharSequence text, int start, int end) {
    for (; start < end; start++) {
      char c = text.charAt(start);
      if (c != ' ' && c != '\t') {
        return start;
      }
    }
    return -1;
  }

  public static void moveCaretToLineEnd(@NotNull Editor editor, boolean isWithSelection) {
    Document document = editor.getDocument();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();
    SoftWrapModel softWrapModel = editor.getSoftWrapModel();

    int lineNumber = editor.getCaretModel().getLogicalPosition().line;
    if (lineNumber >= document.getLineCount()) {
      LogicalPosition pos = new LogicalPosition(lineNumber, 0);
      editor.getCaretModel().moveToLogicalPosition(pos);
      setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
      return;
    }
    VisualPosition currentVisualCaret = editor.getCaretModel().getVisualPosition();
    VisualPosition visualEndOfLineWithCaret
      = new VisualPosition(currentVisualCaret.line, EditorUtil.getLastVisualLineColumnNumber(editor, currentVisualCaret.line));

    // There is a possible case that the caret is already located at the visual end of line and the line is soft wrapped.
    // We want to move the caret to the end of the next visual line then.
    if (currentVisualCaret.equals(visualEndOfLineWithCaret)) {
      LogicalPosition logical = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
      int offset = editor.logicalPositionToOffset(logical);
      if (offset < editor.getDocument().getTextLength()) {

        SoftWrap softWrap = softWrapModel.getSoftWrap(offset);
        if (softWrap == null) {
          // Same offset may correspond to positions on different visual lines in case of soft wraps presence
          // (all soft-wrap introduced virtual text is mapped to the same offset as the first document symbol after soft wrap).
          // Hence, we check for soft wraps presence at two offsets.
          softWrap = softWrapModel.getSoftWrap(offset + 1);
        }
        int line = currentVisualCaret.line;
        int column = currentVisualCaret.column;
        if (softWrap != null) {
          line++;
          column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
        }
        visualEndOfLineWithCaret = new VisualPosition(line, column);
      }
    }

    LogicalPosition logLineEnd = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
    int offset = editor.logicalPositionToOffset(logLineEnd);
    lineNumber = logLineEnd.line;
    int newOffset = offset;

    CharSequence text = document.getCharsSequence();
    for (int i = newOffset - 1; i >= document.getLineStartOffset(lineNumber); i--) {
      if (softWrapModel.getSoftWrap(i) != null) {
        newOffset = offset;
        break;
      }
      if (text.charAt(i) != ' ' && text.charAt(i) != '\t') {
        break;
      }
      newOffset = i;
    }

    // Move to the calculated end of visual line if caret is located on a last non-white space symbols on a line and there are
    // remaining white space symbols.
    if (newOffset == offset || newOffset == caretModel.getOffset()) {
      caretModel.moveToVisualPosition(visualEndOfLineWithCaret);
    }
    else {
      caretModel.moveToOffset(newOffset);
    }

    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);

    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
  }

  public static void moveCaretToNextWord(@NotNull Editor editor, boolean isWithSelection, boolean camel) {
    Document document = editor.getDocument();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();

    int offset = caretModel.getOffset();
    CharSequence text = document.getCharsSequence();
    if (offset == document.getTextLength()) {
      return;
    }
    int newOffset = offset + 1;
    int lineNumber = caretModel.getLogicalPosition().line;
    if (lineNumber >= document.getLineCount()) return;
    int maxOffset = document.getLineEndOffset(lineNumber);
    if (newOffset > maxOffset) {
      if (lineNumber + 1 >= document.getLineCount()) {
        return;
      }
      maxOffset = document.getLineEndOffset(lineNumber + 1);
    }
    for (; newOffset < maxOffset; newOffset++) {
      if (isWordStart(text, newOffset, camel)) {
        break;
      }
    }
    caretModel.moveToOffset(newOffset);
    if (editor.getCaretModel().getCurrentCaret() == editor.getCaretModel().getPrimaryCaret()) {
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    }

    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
  }

  private static void setupSelection(@NotNull Editor editor,
                                     boolean isWithSelection,
                                     int selectionStart,
                                     @NotNull LogicalPosition blockSelectionStart) {
    SelectionModel selectionModel = editor.getSelectionModel();
    CaretModel caretModel = editor.getCaretModel();
    if (isWithSelection) {
      if (editor.isColumnMode() && !caretModel.supportsMultipleCarets()) {
        selectionModel.setBlockSelection(blockSelectionStart, caretModel.getLogicalPosition());
      }
      else {
        selectionModel.setSelection(selectionStart, caretModel.getVisualPosition(), caretModel.getOffset());
      }
    }
    else {
      selectionModel.removeSelection();
    }

    selectNonexpandableFold(editor);
  }

  private static final Key<VisualPosition> PREV_POS = Key.create("PREV_POS");
  public static void selectNonexpandableFold(@NotNull Editor editor) {
    final CaretModel caretModel = editor.getCaretModel();
    final VisualPosition pos = caretModel.getVisualPosition();

    VisualPosition prevPos = editor.getUserData(PREV_POS);

    if (prevPos != null) {
      int columnShift = pos.line == prevPos.line ? pos.column - prevPos.column : 0;

      int caret = caretModel.getOffset();
      final FoldRegion collapsedUnderCaret = editor.getFoldingModel().getCollapsedRegionAtOffset(caret);
      if (collapsedUnderCaret != null && collapsedUnderCaret.shouldNeverExpand()) {
        if (caret > collapsedUnderCaret.getStartOffset() && columnShift > 0) {
          caretModel.moveToOffset(collapsedUnderCaret.getEndOffset());
        }
        else if (caret + 1 < collapsedUnderCaret.getEndOffset() && columnShift < 0) {
          caretModel.moveToOffset(collapsedUnderCaret.getStartOffset());
        }
        editor.getSelectionModel().setSelection(collapsedUnderCaret.getStartOffset(), collapsedUnderCaret.getEndOffset());
      }
    }

    editor.putUserData(PREV_POS, pos);
  }

  public static void moveCaretToPreviousWord(@NotNull Editor editor, boolean isWithSelection, boolean camel) {
    Document document = editor.getDocument();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();

    int offset = editor.getCaretModel().getOffset();
    if (offset == 0) return;

    int lineNumber = editor.getCaretModel().getLogicalPosition().line;
    CharSequence text = document.getCharsSequence();
    int newOffset = offset - 1;
    int minOffset = lineNumber > 0 ? document.getLineEndOffset(lineNumber - 1) : 0;
    for (; newOffset > minOffset; newOffset--) {
      if (isWordStart(text, newOffset, camel)) break;
    }
    editor.getCaretModel().moveToOffset(newOffset);
    if (editor.getCaretModel().getCurrentCaret() == editor.getCaretModel().getPrimaryCaret()) {
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    }

    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
  }

  public static void moveCaretPageUp(@NotNull Editor editor, boolean isWithSelection) {
    int lineHeight = editor.getLineHeight();
    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
    int linesIncrement = visibleArea.height / lineHeight;
    editor.getScrollingModel().scrollVertically(visibleArea.y - visibleArea.y % lineHeight - linesIncrement * lineHeight);
    int lineShift = -linesIncrement;
    editor.getCaretModel().moveCaretRelatively(0, lineShift, isWithSelection, editor.isColumnMode(), true);
  }

  public static void moveCaretPageDown(@NotNull Editor editor, boolean isWithSelection) {
    int lineHeight = editor.getLineHeight();
    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
    int linesIncrement = visibleArea.height / lineHeight;
    int allowedBottom = ((EditorEx)editor).getContentSize().height - visibleArea.height;
    editor.getScrollingModel().scrollVertically(
      Math.min(allowedBottom, visibleArea.y - visibleArea.y % lineHeight + linesIncrement * lineHeight));
    editor.getCaretModel().moveCaretRelatively(0, linesIncrement, isWithSelection, editor.isColumnMode(), true);
  }

  public static void moveCaretPageTop(@NotNull Editor editor, boolean isWithSelection) {
    int lineHeight = editor.getLineHeight();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();
    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
    int lineNumber = visibleArea.y / lineHeight;
    if (visibleArea.y % lineHeight > 0) {
      lineNumber++;
    }
    VisualPosition pos = new VisualPosition(lineNumber, editor.getCaretModel().getVisualPosition().column);
    editor.getCaretModel().moveToVisualPosition(pos);
    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
  }

  public static void moveCaretPageBottom(@NotNull Editor editor, boolean isWithSelection) {
    int lineHeight = editor.getLineHeight();
    SelectionModel selectionModel = editor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    CaretModel caretModel = editor.getCaretModel();
    LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                          ? selectionModel.getBlockStart()
                                          : caretModel.getLogicalPosition();
    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
    int lineNumber = (visibleArea.y + visibleArea.height) / lineHeight - 1;
    VisualPosition pos = new VisualPosition(lineNumber, editor.getCaretModel().getVisualPosition().column);
    editor.getCaretModel().moveToVisualPosition(pos);
    setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
  }

  public static EditorPopupHandler createEditorPopupHandler(@NotNull final String groupId) {
    return new EditorPopupHandler() {
      @Override
      public void invokePopup(final EditorMouseEvent event) {
        if (!event.isConsumed() && event.getArea() == EditorMouseEventArea.EDITING_AREA) {
          ActionGroup group = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(groupId);
          ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.EDITOR_POPUP, group);
          MouseEvent e = event.getMouseEvent();
          final Component c = e.getComponent();
          if (c != null && c.isShowing()) {
            popupMenu.getComponent().show(c, e.getX(), e.getY());
          }
          e.consume();
        }
      }
    };
  }

  public static boolean isHumpBound(@NotNull CharSequence editorText, int offset, boolean start) {
    final char prevChar = editorText.charAt(offset - 1);
    final char curChar = editorText.charAt(offset);
    final char nextChar = offset + 1 < editorText.length() ? editorText.charAt(offset + 1) : 0; // 0x00 is not lowercase.

    return isLowerCaseOrDigit(prevChar) && Character.isUpperCase(curChar) ||
        start && prevChar == '_' && curChar != '_' ||
        !start && prevChar != '_' && curChar == '_' ||
        start && prevChar == '$' && Character.isLetterOrDigit(curChar) ||
        !start && Character.isLetterOrDigit(prevChar) && curChar == '$' ||
        Character.isUpperCase(prevChar) && Character.isUpperCase(curChar) && Character.isLowerCase(nextChar);
  }

  /**
   * This method moves caret to the nearest preceding visual line start, which is not a soft line wrap
   *
   * @see com.intellij.openapi.editor.ex.util.EditorUtil#calcCaretLineRange(com.intellij.openapi.editor.Editor)
   * @see com.intellij.openapi.editor.actions.EditorActionUtil#moveCaretToLineStart(com.intellij.openapi.editor.Editor, boolean)
   */
  public static void moveCaretToLineStartIgnoringSoftWraps(@NotNull Editor editor) {
    editor.getCaretModel().moveToLogicalPosition(EditorUtil.calcCaretLineRange(editor).first);
  }

  /**
   * This method will make required expansions of collapsed region to make given offset 'visible'.
   */
  public static void makePositionVisible(@NotNull final Editor editor, final int offset) {
    FoldingModel foldingModel = editor.getFoldingModel();
    FoldRegion collapsedRegionAtOffset;
    while ((collapsedRegionAtOffset  = foldingModel.getCollapsedRegionAtOffset(offset)) != null) {
      final FoldRegion region = collapsedRegionAtOffset;
      foldingModel.runBatchFoldingOperation(new Runnable() {
        @Override
        public void run() {
          region.setExpanded(true);
        }
      });
    }
  }

  /**
   * Clones caret in a given direction if it's possible. If there already exists a caret at the given direction, removes the current caret.
   *
   * @param editor editor to perform operation in
   * @param caret caret to work on
   * @param above whether to clone the caret above or below
   * @return <code>false</code> if the operation cannot be performed due to current caret being at the edge (top or bottom) of the document,
   * and <code>true</code> otherwise
   */
  public static boolean cloneOrRemoveCaret(Editor editor, Caret caret, boolean above) {
    if (above && caret.getLogicalPosition().line == 0) {
      return false;
    }
    if (!above && caret.getLogicalPosition().line == editor.getDocument().getLineCount() - 1) {
      return false;
    }
    if (caret.clone(above) == null) {
      editor.getCaretModel().removeCaret(caret);
    }
    return true;
  }
}
