/*
 * Copyright 2000-2016 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 vgrechka.phizdetsidea.phizdets.console;

import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingModel;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.FoldingListener;
import com.intellij.util.DocumentUtil;
import vgrechka.phizdetsidea.phizdets.console.pydev.ConsoleCommunicationListener;
import org.jetbrains.annotations.NotNull;

public class PyConsoleStartFolding extends DocumentAdapter implements ConsoleCommunicationListener, FoldingListener {
  private PhizdetsConsoleView myConsoleView;
  private int myNumberOfCommandExecuted = 0;
  private int myNumberOfCommandToStop = 1;
  private boolean doNotAddFoldingAgain = false;
  private FoldRegion myStartFoldRegion;
  private static final String DEFAULT_FOLDING_MESSAGE = "Phizdets Console";
  private int myStartLineOffset = 0;

  public PyConsoleStartFolding(PhizdetsConsoleView consoleView) {
    super();
    myConsoleView = consoleView;
  }

  public void setStartLineOffset(int startLineOffset) {
    myStartLineOffset = startLineOffset;
  }

  public void setNumberOfCommandToStop(int numberOfCommandToStop) {
    myNumberOfCommandToStop = numberOfCommandToStop;
  }

  @Override
  public void documentChanged(DocumentEvent event) {
    addFolding(event);
  }

  private void addFolding(DocumentEvent event) {
    Document document = myConsoleView.getEditor().getDocument();
    if (doNotAddFoldingAgain || document.getTextLength() == 0) {
      return;
    }
    if (myNumberOfCommandExecuted >= myNumberOfCommandToStop) {
      document.removeDocumentListener(this);
      return;
    }
    FoldingModel foldingModel = myConsoleView.getEditor().getFoldingModel();
    foldingModel.runBatchFoldingOperation(() -> {
      int start = myStartLineOffset;
      int finish = document.getTextLength() - 1;
      String placeholderText = DEFAULT_FOLDING_MESSAGE;
      int firstLine = document.getLineNumber(myStartLineOffset);
      for (int line = firstLine; line < document.getLineCount(); line++) {
        String lineText = document.getText(DocumentUtil.getLineTextRange(document, line));
        if (lineText.startsWith("Phizdets")) {
          if (start == myStartLineOffset) {
            start = document.getLineStartOffset(line);
          }
          placeholderText = lineText;
          break;
        }
        if (lineText.startsWith("PyDev console")) {
          start = document.getLineStartOffset(line);
        }
      }
      String newFragment = event.getNewFragment().toString();
      if (newFragment.startsWith("In[") || newFragment.startsWith(PyConsoleUtil.ORDINARY_PROMPT)) {
        finish = event.getOffset() - 1;
        doNotAddFoldingAgain = true;
      }
      if (myStartFoldRegion != null) {
        foldingModel.removeFoldRegion(myStartFoldRegion);
      }
      FoldRegion foldRegion = foldingModel.addFoldRegion(start, finish, placeholderText);
      if (foldRegion != null) {
        foldRegion.setExpanded(false);
        myStartFoldRegion = foldRegion;
      }
    });
  }

  @Override
  public void commandExecuted(boolean more) {
    myNumberOfCommandExecuted++;
  }

  @Override
  public void inputRequested() {

  }

  @Override
  public void onFoldRegionStateChange(@NotNull FoldRegion region) {
    if (region.equals(myStartFoldRegion) && region.isExpanded()) {
      myConsoleView.getEditor().getComponent().updateUI();
      doNotAddFoldingAgain = true;
    }
  }

  @Override
  public void onFoldProcessingEnd() {

  }
}
