/*
 * Copyright 2000-2013 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.jetbrains.python.console;

import com.intellij.codeInsight.hint.HintManager;
import com.intellij.execution.console.LanguageConsoleImpl;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.console.ProcessBackedConsoleExecuteActionHandler;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.codeStyle.IndentHelperImpl;
import com.intellij.util.Function;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.console.pydev.ConsoleCommunication;
import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
import com.jetbrains.python.console.pydev.InterpreterResponse;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.*;

/**
 * @author traff
 */
public class PydevConsoleExecuteActionHandler extends ProcessBackedConsoleExecuteActionHandler implements ConsoleCommunicationListener {
  private final LanguageConsoleView myConsoleView;

  private String myInMultilineStringState = null;
  private StringBuilder myInputBuffer;
  private int myCurrentIndentSize = 0;

  private final ConsoleCommunication myConsoleCommunication;
  private boolean myEnabled = false;

  private int myIpythonInputPromptCount = 1;

  public PydevConsoleExecuteActionHandler(LanguageConsoleView consoleView,
                                          ProcessHandler processHandler,
                                          ConsoleCommunication consoleCommunication) {
    super(processHandler, false);
    myConsoleView = consoleView;
    myConsoleCommunication = consoleCommunication;
    myConsoleCommunication.addCommunicationListener(this);
  }

  @Override
  public void processLine(@NotNull final String text) {
    processLine(text, false);
  }

  public void processLine(@NotNull final String text, boolean execAnyway) {
    int indentBefore = myCurrentIndentSize;
    if (text.isEmpty()) {
      processOneLine(text);
    }
    else {
      if (StringUtil.countNewLines(text.trim()) > 0) {
        executeMultiLine(text);
      }
      else {
        processOneLine(text);
      }
    }
    if (execAnyway && myCurrentIndentSize > 0 && indentBefore == 0) { //if code was indented and we need to exec anyway
      finishExecution();
    }
  }

  private void executeMultiLine(@NotNull String text) {
    if (myInputBuffer == null) {
      myInputBuffer = new StringBuilder();
    }

    myInputBuffer.append(text);

    final LanguageConsoleImpl console = myConsoleView.getConsole();
    final Editor currentEditor = console.getConsoleEditor();

    sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false), console, currentEditor);
  }

  private void processOneLine(String line) {
    int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false);
    line = StringUtil.trimTrailing(line);
    if (StringUtil.isEmptyOrSpaces(line)) {
      doProcessLine("\n");
    }
    else if (indentSize == 0 &&
             indentSize < myCurrentIndentSize &&
             !PyConsoleIndentUtil.shouldIndent(line) &&
             !myConsoleCommunication.isWaitingForInput()) {
      doProcessLine("\n");
      doProcessLine(line);
    }
    else {
      doProcessLine(line);
    }
  }

  public void doProcessLine(final String line) {
    final LanguageConsoleImpl console = myConsoleView.getConsole();
    final Editor currentEditor = console.getConsoleEditor();

    if (myInputBuffer == null) {
      myInputBuffer = new StringBuilder();
    }

    if (!StringUtil.isEmptyOrSpaces(line)) {
      myInputBuffer.append(line);
      if (!line.endsWith("\n")) {
        myInputBuffer.append("\n");
      }
    }

    if (StringUtil.isEmptyOrSpaces(line) && StringUtil.isEmptyOrSpaces(myInputBuffer.toString())) {
      myInputBuffer.append("");
    }

    // multiline strings handling
    if (myInMultilineStringState != null) {
      if (PyConsoleUtil.isDoubleQuoteMultilineStarts(line) || PyConsoleUtil.isSingleQuoteMultilineStarts(line)) {
        myInMultilineStringState = null;
        // restore language
        console.setLanguage(PythonLanguage.getInstance());
        console.setPrompt(PyConsoleUtil.ORDINARY_PROMPT);
      } else {
        if(line.equals("\n")) {
          myInputBuffer.append("\n");
        }
        return;
      }
    }
    else {
      if (PyConsoleUtil.isDoubleQuoteMultilineStarts(line)) {
        myInMultilineStringState = PyConsoleUtil.DOUBLE_QUOTE_MULTILINE;
      }
      else if (PyConsoleUtil.isSingleQuoteMultilineStarts(line)) {
        myInMultilineStringState = PyConsoleUtil.SINGLE_QUOTE_MULTILINE;
      }
      if (myInMultilineStringState != null) {
        // change language
        console.setLanguage(PlainTextLanguage.INSTANCE);
        console.setPrompt(PyConsoleUtil.INDENT_PROMPT);
        return;
      }
    }

    // Process line continuation
    if (line.endsWith("\\")) {
      console.setPrompt(PyConsoleUtil.INDENT_PROMPT);
      return;
    }

    if (!StringUtil.isEmptyOrSpaces(line)) {
      int indent = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false);
      boolean flag = false;
      if (PyConsoleIndentUtil.shouldIndent(line)) {
        indent += getPythonIndent();
        flag = true;
      }
      if ((myCurrentIndentSize > 0 && indent > 0) || flag) {
        setCurrentIndentSize(indent);
        indentEditor(currentEditor, indent);
        more(console, currentEditor);

        myConsoleCommunication.notifyCommandExecuted(true);
        return;
      }
    }


    sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), true), console, currentEditor);
  }

  private void sendLineToConsole(@NotNull final ConsoleCommunication.ConsoleCodeFragment code,
                                 @NotNull final LanguageConsoleImpl console,
                                 @NotNull final Editor currentEditor) {
    if(!StringUtil.isEmptyOrSpaces(code.getText())) {
      myIpythonInputPromptCount+=1;
    }
    if (myConsoleCommunication != null) {
      final boolean waitedForInputBefore = myConsoleCommunication.isWaitingForInput();
      if (myConsoleCommunication.isWaitingForInput()) {
        myInputBuffer.setLength(0);
      }
      else {
        executingPrompt(console);
      }
      myConsoleCommunication.execInterpreter(code, new Function<InterpreterResponse, Object>() {
        @Override
        public Object fun(final InterpreterResponse interpreterResponse) {
          // clear
          myInputBuffer = null;
          // Handle prompt
          if (interpreterResponse.more) {
            more(console, currentEditor);
            if (myCurrentIndentSize == 0) {
              // compute current indentation
              setCurrentIndentSize(
                IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, lastLine(code.getText()), false) + getPythonIndent());
              // In this case we can insert indent automatically
              UIUtil.invokeLaterIfNeeded(new Runnable() {
                @Override
                public void run() {
                  indentEditor(currentEditor, myCurrentIndentSize);
                }
              });
            }
          }
          else {
            if (!myConsoleCommunication.isWaitingForInput()) {
              inPrompt(console, currentEditor);
            }
            setCurrentIndentSize(0);
          }

          return null;
        }
      });
      // After requesting input we got no call back to change prompt, change it manually
      if (waitedForInputBefore && !myConsoleCommunication.isWaitingForInput()) {
        myIpythonInputPromptCount-=1;
        inPrompt(console, currentEditor);
        setCurrentIndentSize(0);
      }
    }
  }

  private static String lastLine(@NotNull String text) {
    String[] lines = StringUtil.splitByLinesDontTrim(text);
    return lines[lines.length - 1];
  }

  private void inPrompt(LanguageConsoleImpl console, Editor currentEditor){
    if(ipythonEnabled(console)){
      ipythonInPrompt(console, currentEditor);
    } else {
      ordinaryPrompt(console, currentEditor);
    }
  }

  private void ordinaryPrompt(LanguageConsoleImpl console, Editor currentEditor) {
    if (!myConsoleCommunication.isExecuting()) {
      if (!PyConsoleUtil.ORDINARY_PROMPT.equals(console.getPrompt())) {
        console.setPrompt(PyConsoleUtil.ORDINARY_PROMPT);
        PyConsoleUtil.scrollDown(currentEditor);
      }
    }
    else {
      executingPrompt(console);
    }
  }

  private boolean ipythonEnabled(LanguageConsoleImpl console){
    return console.getFile().getVirtualFile() != null ?
           PyConsoleUtil.getOrCreateIPythonData(console.getFile().getVirtualFile()).isIPythonEnabled() : false;
  }

  private void ipythonInPrompt(LanguageConsoleImpl console, Editor currentEditor){
    TextAttributes attributes = ConsoleViewContentType.USER_INPUT.getAttributes();
    attributes.setFontType(Font.PLAIN);
    console.setPromptAttributes(attributes);
    console.setPrompt("In[" + myIpythonInputPromptCount + "]:");
    PyConsoleUtil.scrollDown(currentEditor);
  }

  private static void executingPrompt(LanguageConsoleImpl console) {
    console.setPrompt(PyConsoleUtil.EXECUTING_PROMPT);
  }

  private static void more(LanguageConsoleImpl console, Editor currentEditor) {
    if (!PyConsoleUtil.INDENT_PROMPT.equals(console.getPrompt())) {
      console.setPrompt(PyConsoleUtil.INDENT_PROMPT);
      PyConsoleUtil.scrollDown(currentEditor);
    }
  }

  public static String getPrevCommandRunningMessage() {
    return "Previous command is still running. Please wait or press Ctrl+C in console to interrupt.";
  }

  @Override
  public void commandExecuted(boolean more) {
    if (!more) {
      final LanguageConsoleImpl console = myConsoleView.getConsole();
      final Editor currentEditor = console.getConsoleEditor();

      if(!ipythonEnabled(console)){
        ordinaryPrompt(console, currentEditor);
      }
    }
  }

  @Override
  public void inputRequested() {
    final LanguageConsoleImpl console = myConsoleView.getConsole();
    final Editor currentEditor = console.getConsoleEditor();

    if (!PyConsoleUtil.INPUT_PROMPT.equals(console.getPrompt()) && !PyConsoleUtil.HELP_PROMPT.equals(console.getPrompt())) {
      console.setPrompt(PyConsoleUtil.INPUT_PROMPT);
      PyConsoleUtil.scrollDown(currentEditor);
    }
    setCurrentIndentSize(1);
  }

  public void finishExecution() {
    final LanguageConsoleImpl console = myConsoleView.getConsole();
    final Editor currentEditor = console.getConsoleEditor();

    if (myInputBuffer != null) {
      processLine("\n");
    }

    cleanEditor(currentEditor);
    //console.setPrompt(PyConsoleHighlightingUtil.ORDINARY_PROMPT);
  }

  public int getCurrentIndentSize() {
    return myCurrentIndentSize;
  }

  public void setCurrentIndentSize(int currentIndentSize) {
    myCurrentIndentSize = currentIndentSize;
    VirtualFile file = getConsoleFile();
    if (file != null) {
      PyConsoleUtil.setCurrentIndentSize(file, currentIndentSize);
    }
  }

  @Nullable
  private VirtualFile getConsoleFile() {
    if (myConsoleView != null) {
      return myConsoleView.getConsole().getFile().getVirtualFile();
    }
    else {
      return null;
    }
  }

  public int getPythonIndent() {
    return CodeStyleSettingsManager.getSettings(getProject()).getIndentSize(PythonFileType.INSTANCE);
  }

  private void indentEditor(final Editor editor, final int indentSize) {
    new WriteCommandAction(getProject()) {
      @Override
      protected void run(@NotNull Result result) throws Throwable {
        EditorModificationUtil.insertStringAtCaret(editor, IndentHelperImpl.fillIndent(getProject(), PythonFileType.INSTANCE, indentSize));
      }
    }.execute();
  }

  private void cleanEditor(final Editor editor) {
    new WriteCommandAction(getProject()) {
      @Override
      protected void run(@NotNull Result result) throws Throwable {
        editor.getDocument().setText("");
      }
    }.execute();
  }

  private Project getProject() {
    return myConsoleView.getConsole().getProject();
  }

  public String getCantExecuteMessage() {
    if (!isEnabled()) {
      return getConsoleIsNotEnabledMessage();
    }
    else if (!canExecuteNow()) {
      return getPrevCommandRunningMessage();
    }
    else {
      return "Can't execute the command";
    }
  }

  @Override
  public void runExecuteAction(@NotNull LanguageConsoleView console) {
    if (isEnabled()) {
      if (!canExecuteNow()) {
        HintManager.getInstance().showErrorHint(console.getConsole().getConsoleEditor(), getPrevCommandRunningMessage());
      }
      else {
        doRunExecuteAction(console);
      }
    }
    else {
      HintManager.getInstance().showErrorHint(console.getConsole().getConsoleEditor(), getConsoleIsNotEnabledMessage());
    }
  }

  private void doRunExecuteAction(LanguageConsoleView console) {
    if (shouldCopyToHistory(console.getConsole())) {
      copyToHistoryAndExecute(console);
    }
    else {
      processLine(console.getConsole().getConsoleEditor().getDocument().getText());
    }
  }

  private static boolean shouldCopyToHistory(@NotNull LanguageConsoleImpl console) {
    return !PyConsoleUtil.isPagingPrompt(console.getPrompt());
  }

  private void copyToHistoryAndExecute(LanguageConsoleView console) {
    super.runExecuteAction(console);
  }

  public boolean canExecuteNow() {
    return !myConsoleCommunication.isExecuting() || myConsoleCommunication.isWaitingForInput();
  }

  protected String getConsoleIsNotEnabledMessage() {
    return "Console is not enabled.";
  }

  protected void setEnabled(boolean flag) {
    myEnabled = flag;
  }

  public boolean isEnabled() {
    return myEnabled;
  }
}
