/*
 * 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.
 */

package com.intellij.execution.impl;

import com.google.common.base.CharMatcher;
import com.intellij.codeInsight.navigation.IncrementalSearchHandler;
import com.intellij.codeInsight.template.impl.editorActions.TypedActionHandlerBase;
import com.intellij.execution.ConsoleFolding;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.actions.ConsoleActionsPostProcessor;
import com.intellij.execution.actions.EOFAction;
import com.intellij.execution.filters.*;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ObservableConsoleView;
import com.intellij.icons.AllIcons;
import com.intellij.ide.CommonActionsManager;
import com.intellij.ide.OccurenceNavigator;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.*;
import com.intellij.openapi.editor.actions.ScrollToTheEndToolbarAction;
import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.HighlighterClient;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.EditorPopupHandler;
import com.intellij.util.SystemProperties;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableConsoleView, DataProvider, OccurenceNavigator {
  @NonNls private static final String CONSOLE_VIEW_POPUP_MENU = "ConsoleView.PopupMenu";
  private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.ConsoleViewImpl");

  private static final int DEFAULT_FLUSH_DELAY = SystemProperties.getIntProperty("console.flush.delay.ms", 200);

  private static final CharMatcher NEW_LINE_MATCHER = CharMatcher.anyOf("\n\r");

  public static final Key<ConsoleViewImpl> CONSOLE_VIEW_IN_EDITOR_VIEW = Key.create("CONSOLE_VIEW_IN_EDITOR_VIEW");

  static {
    final EditorActionManager actionManager = EditorActionManager.getInstance();
    final TypedAction typedAction = actionManager.getTypedAction();
    typedAction.setupHandler(new MyTypedHandler(typedAction.getHandler()));
  }


  private final CommandLineFolding myCommandLineFolding = new CommandLineFolding();

  private final DisposedPsiManagerCheck myPsiDisposedCheck;
  private final boolean myIsViewer;

  private ConsoleState myState;

  private final Alarm mySpareTimeAlarm = new Alarm(this);
  @Nullable
  private final Alarm myHeavyAlarm;
  private       int   myHeavyUpdateTicket;

  private final Collection<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
  private final List<AnAction> customActions = new ArrayList<AnAction>();
  private final ConsoleBuffer myBuffer = new ConsoleBuffer();
  private boolean myUpdateFoldingsEnabled = true;
  private EditorHyperlinkSupport myHyperlinks;
  private MyDiffContainer myJLayeredPane;
  private JPanel myMainPanel;
  private final Runnable myFinishProgress;
  private boolean myAllowHeavyFilters = false;
  private static final int myFlushDelay = DEFAULT_FLUSH_DELAY;

  private boolean myTooMuchOfOutput;
  private boolean myInDocumentUpdate;

  // If true, then a document is being cleared right now.
  // Should be accessed in EDT only.
  @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
  private boolean myDocumentClearing;
  private int myLastAddedTextLength;
  private int consoleTooMuchTextBufferRatio;

  public Editor getEditor() {
    return myEditor;
  }

  public EditorHyperlinkSupport getHyperlinks() {
    return myHyperlinks;
  }

  public void scrollToEnd() {
    if (myEditor == null) return;
    myEditor.getCaretModel().moveToOffset(myEditor.getDocument().getTextLength());
  }

  public void foldImmediately() {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (!myFlushAlarm.isEmpty()) {
      cancelAllFlushRequests();
      new MyFlushRunnable().run();
    }

    myFoldingAlarm.cancelAllRequests();

    myPendingFoldRegions.clear();
    final FoldingModel model = myEditor.getFoldingModel();
    model.runBatchFoldingOperation(new Runnable() {
      @Override
      public void run() {
        for (FoldRegion region : model.getAllFoldRegions()) {
          model.removeFoldRegion(region);
        }
      }
    });
    myFolding.clear();

    updateFoldings(0, myEditor.getDocument().getLineCount() - 1, true);
  }

  static class TokenInfo {
    final ConsoleViewContentType contentType;
    int startOffset;
    int endOffset;
    private final TextAttributes attributes;

    TokenInfo(final ConsoleViewContentType contentType, final int startOffset, final int endOffset) {
      this.contentType = contentType;
      this.startOffset = startOffset;
      this.endOffset = endOffset;
      attributes = contentType.getAttributes();
    }

    public int getLength() {
      return endOffset - startOffset;
    }

    @Override
    public String toString() {
      return contentType + "[" + startOffset + ";" + endOffset + "]";
    }

    @Nullable
    public HyperlinkInfo getHyperlinkInfo() {
      return null;
    }
  }

  static class HyperlinkTokenInfo extends TokenInfo {
    private final HyperlinkInfo myHyperlinkInfo;

    HyperlinkTokenInfo(final ConsoleViewContentType contentType, final int startOffset, final int endOffset, HyperlinkInfo hyperlinkInfo) {
      super(contentType, startOffset, endOffset);
      myHyperlinkInfo = hyperlinkInfo;
    }

    @Override
    public HyperlinkInfo getHyperlinkInfo() {
      return myHyperlinkInfo;
    }
  }

  private final Project myProject;

  private boolean myOutputPaused;

  private EditorEx myEditor;

  private final Object LOCK = new Object();

  /**
   * Holds number of symbols managed by the current console.
   * <p/>
   * Total number is assembled as a sum of symbols that are already pushed to the document and number of deferred symbols that
   * are awaiting to be pushed to the document.
   */
  private int myContentSize;

  /**
   * Holds information about lexical division by offsets of the text already pushed to document.
   * <p/>
   * Target offsets are anchored to the document here.
   */
  private final List<TokenInfo> myTokens = new ArrayList<TokenInfo>();

  private final TIntObjectHashMap<ConsoleFolding> myFolding = new TIntObjectHashMap<ConsoleFolding>();

  private String myHelpId;

  private final Alarm myFlushUserInputAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this);
  private final Alarm myFlushAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this);

  private final Set<MyFlushRunnable> myCurrentRequests = new HashSet<MyFlushRunnable>();

  protected final CompositeFilter myFilters;

  @Nullable private final InputFilter myInputMessageFilter;

  private final Alarm myFoldingAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this);
  private final List<FoldRegion> myPendingFoldRegions = new ArrayList<FoldRegion>();

  public ConsoleViewImpl(final Project project, boolean viewer) {
    this(project, GlobalSearchScope.allScope(project), viewer, true);
  }

  public ConsoleViewImpl(@NotNull final Project project,
                         @NotNull GlobalSearchScope searchScope,
                         boolean viewer,
                         boolean usePredefinedMessageFilter) {
    this(project, searchScope, viewer,
         new ConsoleState.NotStartedStated() {
           @Override
           public ConsoleState attachTo(ConsoleViewImpl console, ProcessHandler processHandler) {
             return new ConsoleViewRunningState(console, processHandler, this, true, true);
           }
         },
         usePredefinedMessageFilter);
  }

  protected ConsoleViewImpl(@NotNull final Project project,
                            @NotNull GlobalSearchScope searchScope,
                            boolean viewer,
                            @NotNull final ConsoleState initialState,
                            boolean usePredefinedMessageFilter)
  {
    super(new BorderLayout());
    myIsViewer = viewer;
    myState = initialState;
    myPsiDisposedCheck = new DisposedPsiManagerCheck(project);
    myProject = project;

    myFilters = new CompositeFilter(project);
    if (usePredefinedMessageFilter) {
      for (ConsoleFilterProvider eachProvider : Extensions.getExtensions(ConsoleFilterProvider.FILTER_PROVIDERS)) {
        Filter[] filters;
        if (eachProvider instanceof ConsoleDependentFilterProvider) {
          filters = ((ConsoleDependentFilterProvider)eachProvider).getDefaultFilters(this, project, searchScope);
        }
        else if (eachProvider instanceof ConsoleFilterProviderEx) {
          filters = ((ConsoleFilterProviderEx)eachProvider).getDefaultFilters(project, searchScope);
        }
        else {
          filters = eachProvider.getDefaultFilters(project);
        }
        for (Filter filter : filters) {
          myFilters.addFilter(filter);
        }
      }
    }
    myFilters.setForceUseAllFilters(true);
    myHeavyUpdateTicket = 0;
    myHeavyAlarm = myFilters.isAnyHeavy() ? new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this) : null;


    ConsoleInputFilterProvider[] inputFilters = Extensions.getExtensions(ConsoleInputFilterProvider.INPUT_FILTER_PROVIDERS);
    if (inputFilters.length > 0) {
      CompositeInputFilter compositeInputFilter = new CompositeInputFilter(project);
      myInputMessageFilter = compositeInputFilter;
      for (ConsoleInputFilterProvider eachProvider : inputFilters) {
        InputFilter[] filters = eachProvider.getDefaultFilters(project);
        for (final InputFilter filter : filters) {
          compositeInputFilter.addFilter(new InputFilter() {
            boolean isBroken;

            @Nullable
            @Override
            public List<Pair<String, ConsoleViewContentType>> applyFilter(String text, ConsoleViewContentType contentType) {
              if (!isBroken) {
                try {
                  return filter.applyFilter(text, contentType);
                }
                catch (Throwable e) {
                  isBroken = true;
                  LOG.error(e);
                }
              }
              return null;
            }
          });
        }
      }
    }
    else {
      myInputMessageFilter = null;
    }

    myFinishProgress = new Runnable() {
      @Override
      public void run() {
        myJLayeredPane.finishUpdating();
      }
    };
    consoleTooMuchTextBufferRatio = Registry.intValue("console.too.much.text.buffer.ratio");
  }

  @Override
  public void attachToProcess(final ProcessHandler processHandler) {
    myState = myState.attachTo(this, processHandler);
  }

  @Override
  public void clear() {
    if (myEditor == null) return;
    synchronized (LOCK) {
      // real document content will be cleared on next flush;
      myContentSize = 0;
      myBuffer.clear();
      myFolding.clear();
    }
    if (myFlushAlarm.isDisposed()) return;
    cancelAllFlushRequests();
    addFlushRequest(new MyClearRunnable());
    cancelHeavyAlarm();
  }

  @Override
  public void scrollTo(final int offset) {
    if (myEditor == null || myFlushAlarm.isDisposed()) return;
    class ScrollRunnable extends MyFlushRunnable {
      private final int myOffset = offset;

      @Override
      public void doRun() {
        flushDeferredText();
        if (myEditor == null) return;
        int moveOffset = Math.min(offset, myEditor.getDocument().getTextLength());
        if (myBuffer.isUseCyclicBuffer() && moveOffset >= myEditor.getDocument().getTextLength()) {
          moveOffset = 0;
        }
        myEditor.getCaretModel().moveToOffset(moveOffset);
        myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
      }

      @Override
      public boolean equals(Object o) {
        return super.equals(o) && myOffset == ((ScrollRunnable)o).myOffset;
      }
    }
    addFlushRequest(new ScrollRunnable());
  }

  public void requestScrollingToEnd() {
    if (myEditor == null || myFlushAlarm.isDisposed()) {
      return;
    }

    addFlushRequest(new MyFlushRunnable() {
      @Override
      public void doRun() {
        flushDeferredText();
        if (myEditor == null || myFlushAlarm.isDisposed()) {
          return;
        }

        myEditor.getCaretModel().moveToOffset(myEditor.getDocument().getTextLength());
        myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
      }
    });
  }

  private void addFlushRequest(MyFlushRunnable scrollRunnable) {
    addFlushRequest(scrollRunnable, 0);
  }

  private void addFlushRequest(MyFlushRunnable flushRunnable, final int millis) {
    synchronized (myCurrentRequests) {
      if (!myFlushAlarm.isDisposed() && myCurrentRequests.add(flushRunnable)) {
        myFlushAlarm.addRequest(flushRunnable, millis, getStateForUpdate());
      }
    }
  }


  private static void assertIsDispatchThread() {
    ApplicationManager.getApplication().assertIsDispatchThread();
  }

  @Override
  public void setOutputPaused(final boolean value) {
    myOutputPaused = value;
    if (!value) {
      requestFlushImmediately();
    }
  }

  @Override
  public boolean isOutputPaused() {
    return myOutputPaused;
  }

  @Override
  public boolean hasDeferredOutput() {
    synchronized (LOCK) {
      return myBuffer.getLength() > 0;
    }
  }

  @Override
  public void performWhenNoDeferredOutput(final Runnable runnable) {
    //Q: implement in another way without timer?
    if (!hasDeferredOutput()) {
      runnable.run();
    }
    else {
      performLaterWhenNoDeferredOutput(runnable);
    }
  }

  private void performLaterWhenNoDeferredOutput(final Runnable runnable) {
    if (mySpareTimeAlarm.isDisposed()) return;
    mySpareTimeAlarm.addRequest(
      new Runnable() {
        @Override
        public void run() {
          performWhenNoDeferredOutput(runnable);
        }
      },
      100,
      ModalityState.stateForComponent(myJLayeredPane)
    );
  }

  @Override
  public JComponent getComponent() {
    if (myMainPanel == null) {
      myMainPanel = new JPanel(new BorderLayout());
      myJLayeredPane = new MyDiffContainer(myMainPanel, myFilters.getUpdateMessage());
      Disposer.register(this, myJLayeredPane);
      add(myJLayeredPane, BorderLayout.CENTER);
    }

    if (myEditor == null) {
      myEditor = createEditor();
      registerConsoleEditorActions();
      myEditor.getScrollPane().setBorder(null);
      myHyperlinks = new EditorHyperlinkSupport(myEditor, myProject);
      requestFlushImmediately();
      myMainPanel.add(createCenterComponent(), BorderLayout.CENTER);
      myEditor.getScrollingModel().addVisibleAreaListener(new VisibleAreaListener() {
        @Override
        public void visibleAreaChanged(VisibleAreaEvent e) {
          // There is a possible case that the console text is populated while the console is not shown (e.g. we're debugging and
          // 'Debugger' tab is active while 'Console' is not). It's also possible that newly added text contains long lines that
          // are soft wrapped. We want to update viewport position then when the console becomes visible.
          final Rectangle oldRectangle = e.getOldRectangle();
          if (oldRectangle == null) {
            return;
          }

          Editor myEditor = e.getEditor();
          if (oldRectangle.height <= 0 && e.getNewRectangle().height > 0 && myEditor.getSoftWrapModel().isSoftWrappingEnabled()
              && myEditor.getCaretModel().getOffset() == myEditor.getDocument().getTextLength()) {
            EditorUtil.scrollToTheEnd(myEditor);
          }
        }
      });
    }
    return this;
  }

  protected JComponent createCenterComponent() {
    return myEditor.getComponent();
  }

  @Override
  public void dispose() {
    myState = myState.dispose();
    if (myEditor != null) {
      cancelAllFlushRequests();
      mySpareTimeAlarm.cancelAllRequests();
      disposeEditor();
      synchronized (LOCK) {
        myBuffer.clear();
      }
      myEditor = null;
      myHyperlinks = null;
    }
    }

  private void cancelAllFlushRequests() {
    synchronized (myCurrentRequests) {
      for (MyFlushRunnable request : myCurrentRequests) {
        request.invalidate();
      }
      myCurrentRequests.clear();
      myFlushAlarm.cancelAllRequests();
    }
  }

  protected void disposeEditor() {
    UIUtil.invokeAndWaitIfNeeded(new Runnable() {
      @Override
      public void run() {
        if (!myEditor.isDisposed()) {
          EditorFactory.getInstance().releaseEditor(myEditor);
        }
      }
    });
  }

  @Override
  public void print(@NotNull String s, @NotNull ConsoleViewContentType contentType) {
    if (myInputMessageFilter == null) {
      printHyperlink(s, contentType, null);
      return;
    }

    List<Pair<String, ConsoleViewContentType>> result = myInputMessageFilter.applyFilter(s, contentType);
    if (result == null) {
      printHyperlink(s, contentType, null);
    }
    else {
      for (Pair<String, ConsoleViewContentType> pair : result) {
        if (pair.first != null) {
          printHyperlink(pair.first, pair.second == null ? contentType : pair.second, null);
        }
      }
    }
  }

  private void printHyperlink(@NotNull String s, @NotNull ConsoleViewContentType contentType, @Nullable HyperlinkInfo info) {
    synchronized (LOCK) {
      Pair<String, Integer> pair = myBuffer.print(s, contentType, info);
      s = pair.first;
      myContentSize += s.length() - pair.second;

      if (contentType == ConsoleViewContentType.USER_INPUT && NEW_LINE_MATCHER.indexIn(s) >= 0) {
        flushDeferredUserInput();
      }
      if (myEditor != null && !myFlushAlarm.isDisposed()) {
        final boolean shouldFlushNow = myBuffer.isUseCyclicBuffer() && myBuffer.getLength() >= myBuffer.getCyclicBufferSize();
        addFlushRequest(new MyFlushRunnable(), shouldFlushNow ? 0 : myFlushDelay);
      }
    }
  }

  private void addToken(int length, @Nullable HyperlinkInfo info, ConsoleViewContentType contentType) {
    ConsoleUtil.addToken(length, info, contentType, myTokens);
  }

  private static ModalityState getStateForUpdate() {
    return null;//myStateForUpdate != null ? myStateForUpdate.compute() : ModalityState.stateForComponent(this);
  }

  private void requestFlushImmediately() {
    if (myEditor != null && !myFlushAlarm.isDisposed()) {
      addFlushRequest(new MyFlushRunnable());
    }
  }

  @Override
  public int getContentSize() {
    synchronized (LOCK) {
      return myContentSize;
    }
  }

  @Override
  public boolean canPause() {
    return true;
  }

  public void flushDeferredText() {
    flushDeferredText(false);
  }

  private void flushDeferredText(boolean clear) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (myProject.isDisposed()) {
      return;
    }
    EditorEx editor = myEditor;
    if (editor == null) {
      //already disposed
      return;
    }
    if (clear) {
      final DocumentEx document = editor.getDocument();
      synchronized (LOCK) {
        myTokens.clear();
        clearHyperlinkAndFoldings();
      }
      final int documentTextLength = document.getTextLength();
      if (documentTextLength > 0) {
        CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
          @Override
          public void run() {
            document.setInBulkUpdate(true);
            try {
              myInDocumentUpdate = true;
              myDocumentClearing = true;
              document.deleteString(0, documentTextLength);
            }
            finally {
              document.setInBulkUpdate(false);
              myDocumentClearing = false;
              myInDocumentUpdate = false;
            }
          }
        }, null, DocCommandGroupId.noneGroupId(document));
      }
    }


    final String addedText;
    final Collection<ConsoleViewContentType> contentTypes;
    int deferredTokensSize;
    synchronized (LOCK) {
      if (myOutputPaused) return;
      if (myBuffer.isEmpty()) return;

      addedText = myBuffer.getText();

      contentTypes = Collections.unmodifiableCollection(new HashSet<ConsoleViewContentType>(myBuffer.getDeferredTokenTypes()));
      List<TokenInfo> deferredTokens = myBuffer.getDeferredTokens();
      for (TokenInfo deferredToken : deferredTokens) {
        addToken(deferredToken.getLength(), deferredToken.getHyperlinkInfo(), deferredToken.contentType);
      }
      deferredTokensSize = deferredTokens.size();
      myBuffer.clear(false);
      cancelHeavyAlarm();
    }
    final Document document = myEditor.getDocument();
    final RangeMarker lastProcessedOutput = document.createRangeMarker(document.getTextLength(), document.getTextLength());
    final int caretOffset = myEditor.getCaretModel().getOffset();
    final boolean isAtLastLine = isCaretAtLastLine();

    CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
      @Override
      public void run() {
        boolean preserveCurrentVisualArea = caretOffset < document.getTextLength();
        if (preserveCurrentVisualArea) {
          myEditor.getScrollingModel().accumulateViewportChanges();
        }
        try {
          myInDocumentUpdate = true;
          String[] strings = addedText.split("\\r");
          for (int i = 0; i < strings.length - 1; i++) {
            document.insertString(document.getTextLength(), strings[i]);
            int lastLine = document.getLineCount() - 1;
            if (lastLine >= 0) {
              ConsoleUtil.updateTokensOnTextRemoval(myTokens, document.getTextLength(), document.getTextLength() + 1);
              document.deleteString(document.getLineStartOffset(lastLine), document.getTextLength());
            }
          }
          if (strings.length > 0) {
            document.insertString(document.getTextLength(), strings[strings.length - 1]);
            myContentSize -= strings.length - 1;
          }
        }
        finally {
          myInDocumentUpdate = false;
          if (preserveCurrentVisualArea) {
            myEditor.getScrollingModel().flushViewportChanges();
          }
        }
        if (!contentTypes.isEmpty()) {
          for (ChangeListener each : myListeners) {
            each.contentAdded(contentTypes);
          }
        }
      }
    }, null, DocCommandGroupId.noneGroupId(document));
    synchronized (LOCK) {
      for (int i = myTokens.size() - 1; i >= 0 && deferredTokensSize > 0; i--, deferredTokensSize--) {
        TokenInfo token = myTokens.get(i);
        final HyperlinkInfo info = token.getHyperlinkInfo();
        if (info != null) {
          myHyperlinks.createHyperlink(token.startOffset, token.endOffset, null, info);
        }
      }
    }
    myPsiDisposedCheck.performCheck();
    myLastAddedTextLength = addedText.length();
    if (!myTooMuchOfOutput) {
      if (isTheAmountOfTextTooBig(myLastAddedTextLength)) { // disable hyperlinks and folding until new output arriving slows down again
        myTooMuchOfOutput = true;
        final EditorNotificationPanel comp =
          new EditorNotificationPanel().text("Too much output to process").icon(AllIcons.General.ExclMark);
        final Alarm tooMuchOutputAlarm = new Alarm();
        //show the notification with a delay to avoid blinking when "too much output" ceases quickly
        tooMuchOutputAlarm.addRequest(new Runnable() {
          @Override
          public void run() {
            add(comp, BorderLayout.NORTH);
          }
        }, 300);
        performWhenNoDeferredOutput(new Runnable() {
          @Override
          public void run() {
            if (!isTheAmountOfTextTooBig(myLastAddedTextLength)) {
              try {
                highlightHyperlinksAndFoldings(lastProcessedOutput);
              }
              finally {
                myTooMuchOfOutput = false;
                remove(comp);
                tooMuchOutputAlarm.cancelAllRequests();
              }
            }
            else {
              myLastAddedTextLength = 0;
              performLaterWhenNoDeferredOutput(this);
            }
          }
        });
      }
      else {
        highlightHyperlinksAndFoldings(lastProcessedOutput);
      }
    }

    if (isAtLastLine) {
      EditorUtil.scrollToTheEnd(myEditor);
    }
  }

  private boolean isTheAmountOfTextTooBig(final int textLength) {
    return textLength > myBuffer.getCyclicBufferSize() / consoleTooMuchTextBufferRatio;
  }

  private void clearHyperlinkAndFoldings() {
    myEditor.getMarkupModel().removeAllHighlighters();

    myPendingFoldRegions.clear();
    myFolding.clear();
    myFoldingAlarm.cancelAllRequests();
    myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
      @Override
      public void run() {
        myEditor.getFoldingModel().clearFoldRegions();
      }
    });

    cancelHeavyAlarm();
  }

  private void cancelHeavyAlarm() {
    if (myHeavyAlarm != null && !myHeavyAlarm.isDisposed()) {
      myHeavyAlarm.cancelAllRequests();
      ++myHeavyUpdateTicket;
    }
  }

  private void flushDeferredUserInput() {
    final String textToSend = myBuffer.cutFirstUserInputLine();
    if (textToSend == null) {
      return;
    }
    myFlushUserInputAlarm.addRequest(new Runnable() {
      @Override
      public void run() {
        if (myState.isRunning()) {
          try {
            // this may block forever, see IDEA-54340
            myState.sendUserInput(textToSend);
          }
          catch (IOException ignored) {
          }
        }
      }
    }, 0);
  }

  @Override
  public Object getData(final String dataId) {
    if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
      if (myEditor == null) {
        return null;
      }
      final LogicalPosition pos = myEditor.getCaretModel().getLogicalPosition();
      final HyperlinkInfo info = myHyperlinks.getHyperlinkInfoByLineAndCol(pos.line, pos.column);
      final OpenFileDescriptor openFileDescriptor = info instanceof FileHyperlinkInfo ? ((FileHyperlinkInfo)info).getDescriptor() : null;
      if (openFileDescriptor == null || !openFileDescriptor.getFile().isValid()) {
        return null;
      }
      return openFileDescriptor;
    }

    if (CommonDataKeys.EDITOR.is(dataId)) {
      return myEditor;
    }
    if (PlatformDataKeys.HELP_ID.is(dataId)) {
      return myHelpId;
    }
    if (LangDataKeys.CONSOLE_VIEW.is(dataId)) {
      return this;
    }
    return null;
  }

  @Override
  public void setHelpId(final String helpId) {
    myHelpId = helpId;
  }

  public void setUpdateFoldingsEnabled(boolean updateFoldingsEnabled) {
    myUpdateFoldingsEnabled = updateFoldingsEnabled;
  }

  @Override
  public void addMessageFilter(final Filter filter) {
    myFilters.addFilter(filter);
  }

  @Override
  public void printHyperlink(final String hyperlinkText, final HyperlinkInfo info) {
    printHyperlink(hyperlinkText, ConsoleViewContentType.NORMAL_OUTPUT, info);
  }

  private EditorEx createEditor() {
    return ApplicationManager.getApplication().runReadAction(new Computable<EditorEx>() {
      @Override
      public EditorEx compute() {
        EditorEx editor = createRealEditor();
        editor.addEditorMouseListener(new EditorPopupHandler() {
          @Override
          public void invokePopup(final EditorMouseEvent event) {
            popupInvoked(event.getMouseEvent());
          }
        });
        editor.getDocument().addDocumentListener(new DocumentAdapter() {
          @Override
          public void documentChanged(DocumentEvent event) {
            onDocumentChanged(event);
          }
        }, ConsoleViewImpl.this);

        int bufferSize = myBuffer.isUseCyclicBuffer() ? myBuffer.getCyclicBufferSize() : 0;
        editor.getDocument().setCyclicBufferSize(bufferSize);

        editor.putUserData(CONSOLE_VIEW_IN_EDITOR_VIEW, ConsoleViewImpl.this);

        editor.getSettings().setAllowSingleLogicalLineFolding(true); // We want to fold long soft-wrapped command lines
        editor.setHighlighter(createHighlighter());

        return editor;
      }
    });
  }

  private void onDocumentChanged(DocumentEvent event) {
    if (event.getNewLength() == 0) {
      // string has been removed, adjust token ranges
      synchronized (LOCK) {
        ConsoleUtil.updateTokensOnTextRemoval(myTokens, event.getOffset(), event.getOffset() + event.getOldLength());
        int toRemoveLen = event.getOldLength();
        if (!myDocumentClearing) {
          // If document is being cleared now, then this event has been occurred as a result of calling clear() method.
          // At start clear() method sets 'myContentSize' to 0, so there is no need to perform update again.
          // Moreover, performing update of 'myContentSize' breaks executing "console.print();" immediately after "console.clear();".
          myContentSize -= Math.min(myContentSize, toRemoveLen);
        }
      }
    }
    else if (!myInDocumentUpdate) {
      int newFragmentLength = event.getNewFragment().length();
      // track external appends
      if (event.getOldFragment().length() == 0 && newFragmentLength > 0) {
        synchronized (LOCK) {
          myContentSize += newFragmentLength;
          addToken(newFragmentLength, null, ConsoleViewContentType.NORMAL_OUTPUT);
        }
      }
      else {
        LOG.warn("unhandled external change: " + event);
      }
    }
  }

  protected EditorEx createRealEditor() {
    return ConsoleViewUtil.setupConsoleEditor(myProject, true, false);
  }

  protected MyHighlighter createHighlighter() {
    return new MyHighlighter();
  }

  private void registerConsoleEditorActions() {
    HyperlinkNavigationAction hyperlinkNavigationAction = new HyperlinkNavigationAction();
    hyperlinkNavigationAction.registerCustomShortcutSet(CommonShortcuts.ENTER, myEditor.getContentComponent());
    registerActionHandler(myEditor, IdeActions.ACTION_GOTO_DECLARATION, hyperlinkNavigationAction);

    if (!myIsViewer) {
      new EnterHandler().registerCustomShortcutSet(CommonShortcuts.ENTER, myEditor.getContentComponent());
      registerActionHandler(myEditor, IdeActions.ACTION_EDITOR_PASTE, new PasteHandler());
      registerActionHandler(myEditor, IdeActions.ACTION_EDITOR_BACKSPACE, new BackSpaceHandler());
      registerActionHandler(myEditor, IdeActions.ACTION_EDITOR_DELETE, new DeleteHandler());

      registerActionHandler(myEditor, EOFAction.ACTION_ID, ActionManager.getInstance().getAction(EOFAction.ACTION_ID));
    }
  }

  private static void registerActionHandler(final Editor editor, final String actionId, final AnAction action) {
    final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
    final Shortcut[] shortcuts = keymap.getShortcuts(actionId);
    action.registerCustomShortcutSet(new CustomShortcutSet(shortcuts), editor.getContentComponent());
  }

  private void popupInvoked(MouseEvent mouseEvent) {
    final ActionManager actionManager = ActionManager.getInstance();
    final HyperlinkInfo info = myHyperlinks != null ? myHyperlinks.getHyperlinkInfoByPoint(mouseEvent.getPoint()) : null;
    ActionGroup group = null;
    if (info instanceof HyperlinkWithPopupMenuInfo) {
      group = ((HyperlinkWithPopupMenuInfo)info).getPopupMenuGroup(mouseEvent);
    }
    if (group == null) {
      group = (ActionGroup)actionManager.getAction(CONSOLE_VIEW_POPUP_MENU);
    }
    final ConsoleActionsPostProcessor[] postProcessors = Extensions.getExtensions(ConsoleActionsPostProcessor.EP_NAME);
    AnAction[] result = group.getChildren(null);

    for (ConsoleActionsPostProcessor postProcessor : postProcessors) {
      result = postProcessor.postProcessPopupActions(this, result);
    }
    final DefaultActionGroup processedGroup = new DefaultActionGroup(result);
    final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, processedGroup);
    menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
  }

  private void highlightHyperlinksAndFoldings(RangeMarker lastProcessedOutput) {
    boolean canHighlightHyperlinks = !myFilters.isEmpty() || !myFilters.isEmpty();

    if (!canHighlightHyperlinks && myUpdateFoldingsEnabled) {
      return;
    }
    final int line1 = lastProcessedOutput.isValid() ? myEditor.getDocument().getLineNumber(lastProcessedOutput.getEndOffset()) : 0;
    lastProcessedOutput.dispose();
    int endLine = myEditor.getDocument().getLineCount() - 1;
    ApplicationManager.getApplication().assertIsDispatchThread();
    PsiDocumentManager.getInstance(myProject).commitAllDocuments();
    if (canHighlightHyperlinks) {
      myHyperlinks.highlightHyperlinks(myFilters, line1, endLine);
    }

    if (myAllowHeavyFilters && myFilters.isAnyHeavy() && myFilters.shouldRunHeavy()) {
      runHeavyFilters(line1, endLine);
    }
    if (myUpdateFoldingsEnabled) {
      updateFoldings(line1, endLine, true);
    }
  }

  private void runHeavyFilters(int line1, int endLine) {
    final int startLine = Math.max(0, line1);

    final Document document = myEditor.getDocument();
    final int startOffset = document.getLineStartOffset(startLine);
    String text = document.getText(new TextRange(startOffset, document.getLineEndOffset(endLine)));
    final Document documentCopy = new DocumentImpl(text,true);
    documentCopy.setReadOnly(true);

    myJLayeredPane.startUpdating();
    final int currentValue = myHeavyUpdateTicket;
    assert myHeavyAlarm != null;
    myHeavyAlarm.addRequest(new Runnable() {
      @Override
      public void run() {
        if (!myFilters.shouldRunHeavy()) return;
        try {
          myFilters.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer<FilterMixin.AdditionalHighlight>() {
            @Override
            public void consume(final FilterMixin.AdditionalHighlight additionalHighlight) {
              if (myFlushAlarm.isDisposed()) return;
              addFlushRequest(new MyFlushRunnable() {
                @Override
                public void doRun() {
                  if (myHeavyUpdateTicket != currentValue) return;
                  myHyperlinks.addHighlighter(additionalHighlight.getStart(), additionalHighlight.getEnd(),
                                              additionalHighlight.getTextAttributes(null));
                }

                @Override
                public boolean equals(Object o) {
                  return this == o && super.equals(o);
                }
              });
            }
          });
        }
        finally {
          if (myHeavyAlarm.isEmpty()) {
            SwingUtilities.invokeLater(myFinishProgress);
          }
        }
      }
    }, 0);
  }

  private void updateFoldings(final int line1, final int endLine, boolean immediately) {
    final Document document = myEditor.getDocument();
    final CharSequence chars = document.getCharsSequence();
    final int startLine = Math.max(0, line1);
    final List<FoldRegion> toAdd = new ArrayList<FoldRegion>();
    for (int line = startLine; line <= endLine; line++) {
      addFolding(document, chars, line, toAdd);
    }
    if (!toAdd.isEmpty()) {
      doUpdateFolding(toAdd, immediately);
    }
  }

  private void doUpdateFolding(final List<FoldRegion> toAdd, final boolean immediately) {
    assertIsDispatchThread();
    myPendingFoldRegions.addAll(toAdd);

    myFoldingAlarm.cancelAllRequests();
    final Runnable runnable = new Runnable() {
      @Override
      public void run() {
        if (myEditor == null || myEditor.isDisposed()) {
          return;
        }

        assertIsDispatchThread();
        final FoldingModel model = myEditor.getFoldingModel();
        final Runnable operation = new Runnable() {
          @Override
          public void run() {
            assertIsDispatchThread();
            for (FoldRegion region : myPendingFoldRegions) {
              region.setExpanded(false);
              model.addFoldRegion(region);
            }
            myPendingFoldRegions.clear();
          }
        };
        if (immediately) {
          model.runBatchFoldingOperation(operation);
          if (isCaretAtLastLine()) {
            EditorUtil.scrollToTheEnd(myEditor);
          }
        }
        else {
          model.runBatchFoldingOperationDoNotCollapseCaret(operation);
        }
      }
    };
    if (immediately || myPendingFoldRegions.size() > 100) {
      runnable.run();
    }
    else {
      myFoldingAlarm.addRequest(runnable, 50);
    }
  }

  private boolean isCaretAtLastLine() {
    final Document document = myEditor.getDocument();
    final int caretOffset = myEditor.getCaretModel().getOffset();
    return document.getLineNumber(caretOffset) >= document.getLineCount() - 1;
  }

  private void addFolding(Document document, CharSequence chars, int line, List<FoldRegion> toAdd) {
    String commandLinePlaceholder = myCommandLineFolding.getPlaceholder(line);
    if (commandLinePlaceholder != null) {
      FoldRegion region = myEditor.getFoldingModel().createFoldRegion(
        document.getLineStartOffset(line), document.getLineEndOffset(line), commandLinePlaceholder, null, false
      );
      toAdd.add(region);
      return;
    }
    ConsoleFolding current = foldingForLine(EditorHyperlinkSupport.getLineText(document, line, false));
    if (current != null) {
      myFolding.put(line, current);
    }

    final ConsoleFolding prevFolding = myFolding.get(line - 1);
    if (current == null && prevFolding != null) {
      final int lEnd = line - 1;
      int lStart = lEnd;
      while (prevFolding.equals(myFolding.get(lStart - 1))) lStart--;

      for (int i = lStart; i <= lEnd; i++) {
        myFolding.remove(i);
      }

      List<String> toFold = new ArrayList<String>(lEnd - lStart + 1);
      for (int i = lStart; i <= lEnd; i++) {
        toFold.add(EditorHyperlinkSupport.getLineText(document, i, false));
      }

      int oStart = document.getLineStartOffset(lStart);
      if (oStart > 0) oStart--;
      int oEnd = CharArrayUtil.shiftBackward(chars, document.getLineEndOffset(lEnd) - 1, " \t") + 1;

      String placeholder = prevFolding.getPlaceholderText(toFold);
      FoldRegion region = placeholder == null ? null : myEditor.getFoldingModel().createFoldRegion(oStart, oEnd, placeholder, null, false);
      if (region != null) {
        toAdd.add(region);
      }
    }
  }

  @Nullable
  private static ConsoleFolding foldingForLine(String lineText) {
    for (ConsoleFolding folding : ConsoleFolding.EP_NAME.getExtensions()) {
      if (folding.shouldFoldLine(lineText)) {
        return folding;
      }
    }
    return null;
  }


  public static class ClearAllAction extends DumbAwareAction {
    public ClearAllAction() {
      super(ExecutionBundle.message("clear.all.from.console.action.name"), "Clear the contents of the console", AllIcons.Actions.GC);
    }

    @Override
    public void update(AnActionEvent e) {
      boolean enabled = e.getData(LangDataKeys.CONSOLE_VIEW) != null;
      Editor editor = e.getData(CommonDataKeys.EDITOR);
      if (editor != null && editor.getDocument().getTextLength() == 0) {
        enabled = false;
      }
      e.getPresentation().setEnabled(enabled);
    }

    @Override
    public void actionPerformed(final AnActionEvent e) {
      final ConsoleView consoleView = e.getData(LangDataKeys.CONSOLE_VIEW);
      if (consoleView != null) {
        consoleView.clear();
      }
    }
  }

  private class MyHighlighter extends DocumentAdapter implements EditorHighlighter {
    private HighlighterClient myEditor;

    @NotNull
    @Override
    public HighlighterIterator createIterator(final int startOffset) {
      final int startIndex = ConsoleUtil.findTokenInfoIndexByOffset(myTokens, startOffset);

      return new HighlighterIterator() {
        private int myIndex = startIndex;

        @Override
        public TextAttributes getTextAttributes() {
          return getTokenInfo() == null ? null : getTokenInfo().attributes;
        }

        @Override
        public int getStart() {
          return getTokenInfo() == null ? 0 : getTokenInfo().startOffset;
        }

        @Override
        public int getEnd() {
          return getTokenInfo() == null ? 0 : getTokenInfo().endOffset;
        }

        @Override
        public IElementType getTokenType() {
          return null;
        }

        @Override
        public void advance() {
          myIndex++;
        }

        @Override
        public void retreat() {
          myIndex--;
        }

        @Override
        public boolean atEnd() {
          return myIndex < 0 || myIndex >= myTokens.size();
        }

        @Override
        public Document getDocument() {
          return myEditor.getDocument();
        }

        private TokenInfo getTokenInfo() {
          return myTokens.get(myIndex);
        }
      };
    }

    @Override
    public void setText(@NotNull final CharSequence text) {
    }

    @Override
    public void setEditor(@NotNull final HighlighterClient editor) {
      LOG.assertTrue(myEditor == null, "Highlighters cannot be reused with different editors");
      myEditor = editor;
    }

    @Override
    public void setColorScheme(@NotNull EditorColorsScheme scheme) {
    }
  }

  private static class MyTypedHandler extends TypedActionHandlerBase {

    private MyTypedHandler(final TypedActionHandler originalAction) {
      super(originalAction);
    }

    @Override
    public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext dataContext) {
      final ConsoleViewImpl consoleView = editor.getUserData(CONSOLE_VIEW_IN_EDITOR_VIEW);
      if (consoleView == null || !consoleView.myState.isRunning() || consoleView.myIsViewer) {
        if (myOriginalHandler != null) myOriginalHandler.execute(editor, charTyped, dataContext);
      }
      else {
        final String s = String.valueOf(charTyped);
        SelectionModel selectionModel = editor.getSelectionModel();
        if (selectionModel.hasSelection()) {
          consoleView.replaceUserText(s, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
        }
        else {
          consoleView.insertUserText(s, editor.getCaretModel().getOffset());
        }
      }
    }
  }

  private abstract static class ConsoleAction extends AnAction implements DumbAware {
    @Override
    public void actionPerformed(final AnActionEvent e) {
      final DataContext context = e.getDataContext();
      final ConsoleViewImpl console = getRunningConsole(context);
      execute(console, context);
    }

    protected abstract void execute(ConsoleViewImpl console, final DataContext context);

    @Override
    public void update(final AnActionEvent e) {
      final ConsoleViewImpl console = getRunningConsole(e.getDataContext());
      e.getPresentation().setEnabled(console != null);
    }

    @Nullable
    private static ConsoleViewImpl getRunningConsole(final DataContext context) {
      final Editor editor = CommonDataKeys.EDITOR.getData(context);
      if (editor != null) {
        final ConsoleViewImpl console = editor.getUserData(CONSOLE_VIEW_IN_EDITOR_VIEW);
        if (console != null && console.myState.isRunning()) {
          return console;
        }
      }
      return null;
    }
  }

  private static class EnterHandler extends ConsoleAction {
    @Override
    public void execute(final ConsoleViewImpl consoleView, final DataContext context) {
      consoleView.print("\n", ConsoleViewContentType.USER_INPUT);
      consoleView.flushDeferredText();
      final Editor editor = consoleView.myEditor;
      editor.getCaretModel().moveToOffset(editor.getDocument().getTextLength());
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    }
  }

  private static class PasteHandler extends ConsoleAction {
    @Override
    public void execute(final ConsoleViewImpl consoleView, final DataContext context) {
      String s = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
      if (s == null) return;
      ApplicationManager.getApplication().assertIsDispatchThread();
      Editor editor = consoleView.myEditor;
      SelectionModel selectionModel = editor.getSelectionModel();
      if (selectionModel.hasSelection()) {
        consoleView.replaceUserText(s, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
      }
      else {
        consoleView.insertUserText(s, editor.getCaretModel().getOffset());
      }
    }
  }

  private static class BackSpaceHandler extends ConsoleAction {
    @Override
    public void execute(final ConsoleViewImpl consoleView, final DataContext context) {
      final Editor editor = consoleView.myEditor;

      if (IncrementalSearchHandler.isHintVisible(editor)) {
        getDefaultActionHandler().execute(editor, context);
        return;
      }

      final Document document = editor.getDocument();
      final int length = document.getTextLength();
      if (length == 0) {
        return;
      }

      ApplicationManager.getApplication().assertIsDispatchThread();

      SelectionModel selectionModel = editor.getSelectionModel();
      if (selectionModel.hasSelection()) {
        consoleView.deleteUserText(selectionModel.getSelectionStart(),
                                   selectionModel.getSelectionEnd() - selectionModel.getSelectionStart());
      }
      else if (editor.getCaretModel().getOffset() > 0) {
        consoleView.deleteUserText(editor.getCaretModel().getOffset() - 1, 1);
      }
    }

    private static EditorActionHandler getDefaultActionHandler() {
      return EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE);
    }
  }

  private static class DeleteHandler extends ConsoleAction {
    @Override
    public void execute(final ConsoleViewImpl consoleView, final DataContext context) {
      final Editor editor = consoleView.myEditor;

      if (IncrementalSearchHandler.isHintVisible(editor)) {
        getDefaultActionHandler().execute(editor, context);
        return;
      }

      final Document document = editor.getDocument();
      final int length = document.getTextLength();
      if (length == 0) {
        return;
      }

      ApplicationManager.getApplication().assertIsDispatchThread();
      SelectionModel selectionModel = editor.getSelectionModel();
      if (selectionModel.hasSelection()) {
        consoleView.deleteUserText(selectionModel.getSelectionStart(),
                                   selectionModel.getSelectionEnd() - selectionModel.getSelectionStart());
      }
      else {
        consoleView.deleteUserText(editor.getCaretModel().getOffset(), 1);
      }
    }

    private static EditorActionHandler getDefaultActionHandler() {
      return EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE);
    }
  }

  @Override
  public JComponent getPreferredFocusableComponent() {
    //ensure editor created
    getComponent();
    return myEditor.getContentComponent();
  }


  // navigate up/down in stack trace
  @Override
  public boolean hasNextOccurence() {
    return calcNextOccurrence(1) != null;
  }

  @Override
  public boolean hasPreviousOccurence() {
    return calcNextOccurrence(-1) != null;
  }

  @Override
  public OccurenceInfo goNextOccurence() {
    return calcNextOccurrence(1);
  }

  @Nullable
  protected OccurenceInfo calcNextOccurrence(final int delta) {
    final EditorHyperlinkSupport hyperlinks = myHyperlinks;
    if (hyperlinks == null) {
      return null;
    }

    return EditorHyperlinkSupport.getNextOccurrence(myEditor, delta, new Consumer<RangeHighlighter>() {
      @Override
      public void consume(RangeHighlighter next) {
        int offset = next.getStartOffset();
        scrollTo(offset);
        final HyperlinkInfo hyperlinkInfo = EditorHyperlinkSupport.getHyperlinkInfo(next);
        if (hyperlinkInfo instanceof HyperlinkInfoBase) {
          VisualPosition position = myEditor.offsetToVisualPosition(offset);
          Point point = myEditor.visualPositionToXY(new VisualPosition(position.getLine() + 1, position.getColumn()));
          ((HyperlinkInfoBase)hyperlinkInfo).navigate(myProject, new RelativePoint(myEditor.getContentComponent(), point));
        }
        else if (hyperlinkInfo != null) {
          hyperlinkInfo.navigate(myProject);
        }
      }
    });
  }

  @Override
  public OccurenceInfo goPreviousOccurence() {
    return calcNextOccurrence(-1);
  }

  @Override
  public String getNextOccurenceActionName() {
    return ExecutionBundle.message("down.the.stack.trace");
  }

  @Override
  public String getPreviousOccurenceActionName() {
    return ExecutionBundle.message("up.the.stack.trace");
  }

  public void addCustomConsoleAction(@NotNull AnAction action) {
    customActions.add(action);
  }

  @Override
  @NotNull
  public AnAction[] createConsoleActions() {
    //Initializing prev and next occurrences actions
    final CommonActionsManager actionsManager = CommonActionsManager.getInstance();
    final AnAction prevAction = actionsManager.createPrevOccurenceAction(this);
    prevAction.getTemplatePresentation().setText(getPreviousOccurenceActionName());
    final AnAction nextAction = actionsManager.createNextOccurenceAction(this);
    nextAction.getTemplatePresentation().setText(getNextOccurenceActionName());

    final AnAction switchSoftWrapsAction = new ToggleUseSoftWrapsToolbarAction(SoftWrapAppliancePlaces.CONSOLE) {

      /**
       * There is a possible case that more than console is open and user toggles soft wraps mode at one of them. We want
       * to update another console(s) representation as well when they are switched on after that. Hence, we remember last
       * used soft wraps mode and perform update if we see that the current value differs from the stored.
       */
      private boolean myLastIsSelected;

      @Override
      protected Editor getEditor(AnActionEvent e) {
        return myEditor;
      }

      @Override
      public boolean isSelected(AnActionEvent e) {
        boolean result = super.isSelected(e);
        if (result ^ myLastIsSelected) {
          setSelected(null, result);
        }
        return myLastIsSelected = result;
      }

      @Override
      public void setSelected(AnActionEvent e, final boolean state) {
        super.setSelected(e, state);
        if (myEditor == null) {
          return;
        }

        final String placeholder = myCommandLineFolding.getPlaceholder(0);
        final FoldingModel foldingModel = myEditor.getFoldingModel();
        final int firstLineEnd = myEditor.getDocument().getLineEndOffset(0);
        foldingModel.runBatchFoldingOperation(new Runnable() {
          @Override
          public void run() {
            FoldRegion[] regions = foldingModel.getAllFoldRegions();
            if (regions.length > 0 && regions[0].getStartOffset() == 0 && regions[0].getEndOffset() == firstLineEnd) {
              foldingModel.removeFoldRegion(regions[0]);
            }
            if (placeholder != null) {
              FoldRegion foldRegion = foldingModel.addFoldRegion(0, firstLineEnd, placeholder);
              if (foldRegion != null) {
                foldRegion.setExpanded(false);
              }
            }
          }
        });
      }
    };
    final AnAction autoScrollToTheEndAction = new ScrollToTheEndToolbarAction(myEditor);

    //Initializing custom actions
    final AnAction[] consoleActions = new AnAction[6 + customActions.size()];
    consoleActions[0] = prevAction;
    consoleActions[1] = nextAction;
    consoleActions[2] = switchSoftWrapsAction;
    consoleActions[3] = autoScrollToTheEndAction;
    consoleActions[4] = ActionManager.getInstance().getAction("Print");
    consoleActions[5] = new ClearAllAction();
    for (int i = 0; i < customActions.size(); ++i) {
      consoleActions[i + 6] = customActions.get(i);
    }
    ConsoleActionsPostProcessor[] postProcessors = Extensions.getExtensions(ConsoleActionsPostProcessor.EP_NAME);
    AnAction[] result = consoleActions;
    for (ConsoleActionsPostProcessor postProcessor : postProcessors) {
      result = postProcessor.postProcess(this, result);
    }
    return result;
  }

  @Override
  public void allowHeavyFilters() {
    myAllowHeavyFilters = true;
  }

  @Override
  public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) {
    myListeners.add(listener);
    Disposer.register(parent, new Disposable() {
      @Override
      public void dispose() {
        myListeners.remove(listener);
      }
    });
  }

  /**
   * insert text to document
   *
   * @param s      inserted text
   * @param offset relatively to all document text
   */
  private void insertUserText(final String s, int offset) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    final ConsoleViewImpl consoleView = this;
    final ConsoleBuffer buffer = consoleView.myBuffer;
    final Editor editor = consoleView.myEditor;
    final Document document = editor.getDocument();
    final int startOffset;

    String textToUse = StringUtil.convertLineSeparators(s);
    synchronized (consoleView.LOCK) {
      if (consoleView.myTokens.isEmpty()) return;
      final TokenInfo info = consoleView.myTokens.get(consoleView.myTokens.size() - 1);
      if (info.contentType != ConsoleViewContentType.USER_INPUT && !StringUtil.containsChar(textToUse, '\n')) {
        consoleView.print(textToUse, ConsoleViewContentType.USER_INPUT);
        consoleView.flushDeferredText();
        editor.getCaretModel().moveToOffset(document.getTextLength());
        editor.getSelectionModel().removeSelection();
        return;
      }
      if (info.contentType != ConsoleViewContentType.USER_INPUT) {
        insertUserText("temp", offset);
        final TokenInfo newInfo = consoleView.myTokens.get(consoleView.myTokens.size() - 1);
        replaceUserText(textToUse, newInfo.startOffset, newInfo.endOffset);
        return;
      }

      final int deferredOffset = myContentSize - buffer.getLength() - buffer.getUserInputLength();
      if (offset > info.endOffset) {
        startOffset = info.endOffset;
      }
      else {
        startOffset = Math.max(deferredOffset, Math.max(info.startOffset, offset));
      }

      buffer.addUserText(startOffset - deferredOffset, textToUse);

      int charCountToAdd = textToUse.length();
      info.endOffset += charCountToAdd;
      consoleView.myContentSize += charCountToAdd;
    }

    try {
      myInDocumentUpdate = true;
      document.insertString(startOffset, textToUse);
    }
    finally {
      myInDocumentUpdate = false;
    }
    // Math.max is needed when cyclic buffer is used
    editor.getCaretModel().moveToOffset(Math.min(startOffset + textToUse.length(), document.getTextLength()));
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
  }

  /**
   * replace text
   *
   * @param s     text for replace
   * @param start relatively to all document text
   * @param end   relatively to all document text
   */
  private void replaceUserText(final String s, int start, int end) {
    if (start == end) {
      insertUserText(s, start);
      return;
    }
    final ConsoleViewImpl consoleView = this;
    final ConsoleBuffer buffer = consoleView.myBuffer;
    final Editor editor = consoleView.myEditor;
    final Document document = editor.getDocument();
    final int startOffset;
    final int endOffset;

    synchronized (consoleView.LOCK) {
      if (consoleView.myTokens.isEmpty()) return;
      final TokenInfo info = consoleView.myTokens.get(consoleView.myTokens.size() - 1);
      if (info.contentType != ConsoleViewContentType.USER_INPUT) {
        consoleView.print(s, ConsoleViewContentType.USER_INPUT);
        consoleView.flushDeferredText();
        editor.getCaretModel().moveToOffset(document.getTextLength());
        editor.getSelectionModel().removeSelection();
        return;
      }
      if (buffer.getUserInputLength() <= 0) return;

      final int deferredOffset = myContentSize - buffer.getLength() - buffer.getUserInputLength();

      startOffset = getStartOffset(start, info, deferredOffset);
      endOffset = getEndOffset(end, info);

      if (startOffset == -1 ||
          endOffset == -1 ||
          endOffset <= startOffset) {
        editor.getSelectionModel().removeSelection();
        editor.getCaretModel().moveToOffset(start);
        return;
      }
      int charCountToReplace = s.length() - endOffset + startOffset;

      buffer.replaceUserText(startOffset - deferredOffset, endOffset - deferredOffset, s);

      info.endOffset += charCountToReplace;
      if (info.startOffset == info.endOffset) {
        consoleView.myTokens.remove(consoleView.myTokens.size() - 1);
      }
      consoleView.myContentSize += charCountToReplace;
    }

    try {
      myInDocumentUpdate = true;
      document.replaceString(startOffset, endOffset, s);
    }
    finally {
      myInDocumentUpdate = false;
    }
    editor.getCaretModel().moveToOffset(startOffset + s.length());
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    editor.getSelectionModel().removeSelection();
  }

  /**
   * delete text
   *
   * @param offset relatively to all document text
   * @param length length of deleted text
   */
  private void deleteUserText(int offset, int length) {
    ConsoleViewImpl consoleView = this;
    ConsoleBuffer buffer = consoleView.myBuffer;
    final Editor editor = consoleView.myEditor;
    final Document document = editor.getDocument();
    final int startOffset;
    final int endOffset;

    synchronized (consoleView.LOCK) {
      if (consoleView.myTokens.isEmpty()) return;
      final TokenInfo info = consoleView.myTokens.get(consoleView.myTokens.size() - 1);
      if (info.contentType != ConsoleViewContentType.USER_INPUT) return;
      if (myBuffer.getUserInputLength() == 0) return;

      final int deferredOffset = myContentSize - buffer.getLength() - buffer.getUserInputLength();
      startOffset = getStartOffset(offset, info, deferredOffset);
      endOffset = getEndOffset(offset + length, info);
      if (startOffset == -1 ||
          endOffset == -1 ||
          endOffset <= startOffset ||
          startOffset < deferredOffset) {
        editor.getSelectionModel().removeSelection();
        editor.getCaretModel().moveToOffset(offset);
        return;
      }

      buffer.removeUserText(startOffset - deferredOffset, endOffset - deferredOffset);
    }

    try {
      myInDocumentUpdate = true;
      document.deleteString(startOffset, endOffset);
    }
    finally {
      myInDocumentUpdate = false;
    }
    editor.getCaretModel().moveToOffset(startOffset);
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    editor.getSelectionModel().removeSelection();
  }

  //util methods for add, replace, delete methods
  private static int getStartOffset(int offset, TokenInfo info, int deferredOffset) {
    int startOffset;
    if (offset >= info.startOffset && offset < info.endOffset) {
      startOffset = Math.max(offset, deferredOffset);
    }
    else if (offset < info.startOffset) {
      startOffset = Math.max(info.startOffset, deferredOffset);
    }
    else {
      startOffset = -1;
    }
    return startOffset;
  }

  private static int getEndOffset(int offset, TokenInfo info) {
    int endOffset;
    if (offset > info.endOffset) {
      endOffset = info.endOffset;
    }
    else if (offset <= info.startOffset) {
      endOffset = -1;
    }
    else {
      endOffset = offset;
    }
    return endOffset;
  }

  public boolean isRunning() {
    return myState.isRunning();
  }

  /**
   * Command line used to launch application/test from idea may be quite long.
   * Hence, it takes many visual lines during representation if soft wraps are enabled
   * or, otherwise, takes many columns and makes horizontal scrollbar thumb too small.
   * <p/>
   * Our point is to fold such long command line and represent it as a single visual line by default.
   */
  private class CommandLineFolding extends ConsoleFolding {

    /**
     * Checks if target line should be folded and returns its placeholder if the examination succeeds.
     *
     * @param line index of line to check
     * @return placeholder text if given line should be folded; <code>null</code> otherwise
     */
    @Nullable
    public String getPlaceholder(int line) {
      if (myEditor == null || line != 0) {
        return null;
      }

      String text = EditorHyperlinkSupport.getLineText(myEditor.getDocument(), 0, false);
      // Don't fold the first line if the line is not that big.
      if (text.length() < 1000) {
        return null;
      }
      boolean nonWhiteSpaceFound = false;
      int index = 0;
      for (; index < text.length(); index++) {
        char c = text.charAt(index);
        if (c != ' ' && c != '\t') {
          nonWhiteSpaceFound = true;
          continue;
        }
        if (nonWhiteSpaceFound) {
          break;
        }
      }
      assert index <= text.length();
      return text.substring(0, index) + " ...";
    }

    @Override
    public boolean shouldFoldLine(String line) {
      return false;
    }

    @Override
    public String getPlaceholderText(List<String> lines) {
      // Is not expected to be called.
      return "<...>";
    }
  }

  private class MyFlushRunnable implements Runnable {
    private volatile boolean myValid = true;
    @Override
    public final void run() {
      synchronized (myCurrentRequests) {
        myCurrentRequests.remove(this);
      }
      if (myValid) {
        doRun();
      }
    }

    protected void doRun() {
      flushDeferredText();
    }

    public void invalidate() {
      myValid = false;
    }

    public boolean isValid() {
      return myValid;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      MyFlushRunnable runnable = (MyFlushRunnable)o;

      return myValid == runnable.myValid;
    }

    @Override
    public int hashCode() {
      return getClass().hashCode();
    }
  }

  private final class MyClearRunnable extends MyFlushRunnable {
    @Override
    public void doRun() {
      flushDeferredText(true);
    }
  }

  @NotNull
  public Project getProject() {
    return myProject;
  }

  private class HyperlinkNavigationAction extends DumbAwareAction {
    @Override
    public void actionPerformed(AnActionEvent e) {
      Runnable runnable = myHyperlinks.getLinkNavigationRunnable(myEditor.getCaretModel().getLogicalPosition());
      assert runnable != null;
      runnable.run();
    }

    @Override
    public void update(AnActionEvent e) {
      e.getPresentation().setEnabled(myHyperlinks.getLinkNavigationRunnable(myEditor.getCaretModel().getLogicalPosition()) != null);
    }
  }
}

