/*
 * 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 org.jetbrains.plugins.groovy.editor.actions;

import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.text.CharArrayCharSequence;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.codeStyle.GroovyCodeStyleSettings;
import org.jetbrains.plugins.groovy.editor.HandlerUtils;
import org.jetbrains.plugins.groovy.formatter.GeeseUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;

import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCLOSABLE_BLOCK_OP;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_BEGIN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_CONTENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_END;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_LITERAL;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGSTRING_BEGIN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGSTRING_CONTENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGSTRING_END;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGSTRING_LITERAL;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mIDENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mLBRACK;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mLCURLY;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mNLS;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mRBRACK;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mRCURLY;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mREGEX_BEGIN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mREGEX_CONTENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mREGEX_END;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mREGEX_LITERAL;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mSTRING_LITERAL;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;

/**
 * @author ilyas
 */
public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {

  private static final TokenSet GSTRING_TOKENS = TokenSet.create(mGSTRING_BEGIN, mGSTRING_CONTENT, mGSTRING_END, mGSTRING_LITERAL);

  private static final TokenSet REGEX_TOKENS = TokenSet.create(mREGEX_BEGIN, mREGEX_CONTENT, mREGEX_END, mDOLLAR_SLASH_REGEX_BEGIN,
                                                         mDOLLAR_SLASH_REGEX_CONTENT, mDOLLAR_SLASH_REGEX_END);

  private static final TokenSet AFTER_DOLLAR = TokenSet.create(mLCURLY, mIDENT, mDOLLAR, mGSTRING_END, mREGEX_END, mDOLLAR_SLASH_REGEX_END,
                                                               GSTRING_CONTENT, mGSTRING_CONTENT, mREGEX_CONTENT, mDOLLAR_SLASH_REGEX_CONTENT);

  private static final TokenSet ALL_STRINGS = TokenSet.create(mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_BEGIN, mGSTRING_END,
                                                              mGSTRING_CONTENT, mRCURLY, mIDENT, mDOLLAR, mREGEX_BEGIN, mREGEX_CONTENT,
                                                              mREGEX_END, mDOLLAR_SLASH_REGEX_BEGIN, mDOLLAR_SLASH_REGEX_CONTENT,
                                                              mDOLLAR_SLASH_REGEX_END, mREGEX_LITERAL, mDOLLAR_SLASH_REGEX_LITERAL, GSTRING_CONTENT);

  private static final TokenSet BEFORE_DOLLAR =TokenSet.create(mGSTRING_BEGIN, mREGEX_BEGIN, mDOLLAR_SLASH_REGEX_BEGIN, GSTRING_CONTENT,
                                                               mGSTRING_CONTENT, mREGEX_CONTENT, mDOLLAR_SLASH_REGEX_CONTENT);

  private static final TokenSet EXPR_END = TokenSet.create(mRCURLY, mIDENT);

  private static final TokenSet AFTER_EXPR_END = TokenSet.create(mGSTRING_END, mDOLLAR, mREGEX_END, mDOLLAR_SLASH_REGEX_END, GSTRING_CONTENT,
                                                                 mGSTRING_CONTENT, mREGEX_CONTENT, mDOLLAR_SLASH_REGEX_CONTENT);

  private static final TokenSet STRING_END = TokenSet.create(mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_END, mREGEX_END,
                                                             mDOLLAR_SLASH_REGEX_END, mREGEX_LITERAL, mDOLLAR_SLASH_REGEX_LITERAL);

  private static final TokenSet INNER_STRING_TOKENS = TokenSet.create(mGSTRING_BEGIN, mGSTRING_CONTENT, mGSTRING_END, mREGEX_BEGIN,
                                                                       mREGEX_CONTENT, mREGEX_END, mDOLLAR_SLASH_REGEX_BEGIN,
                                                                       mDOLLAR_SLASH_REGEX_CONTENT, mDOLLAR_SLASH_REGEX_END,
                                                                       GSTRING_INJECTION, GSTRING_CONTENT);

  public static void insertSpacesByGroovyContinuationIndent(Editor editor, Project project) {
    int indentSize = CodeStyleSettingsManager.getSettings(project).getContinuationIndentSize(GroovyFileType.GROOVY_FILE_TYPE);
    EditorModificationUtil.insertStringAtCaret(editor, StringUtil.repeatSymbol(' ', indentSize));
  }


  public Result preprocessEnter(@NotNull PsiFile file,
                                @NotNull Editor editor,
                                @NotNull Ref<Integer> caretOffset,
                                @NotNull Ref<Integer> caretAdvance,
                                @NotNull DataContext dataContext,
                                EditorActionHandler originalHandler) {
    Document document = editor.getDocument();
    Project project = file.getProject();
    CaretModel caretModel = editor.getCaretModel();

    String text = document.getText();
    if (StringUtil.isEmpty(text)) {
      return Result.Continue;
    }

    if (!(file instanceof GroovyFileBase)) {
      return Result.Continue;
    }

    final int caret = caretModel.getOffset();
    final EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
    if (caret >= 1 && caret < text.length() && CodeInsightSettings.getInstance().SMART_INDENT_ON_ENTER) {
      HighlighterIterator iterator = highlighter.createIterator(caret);
      iterator.retreat();
      while (!iterator.atEnd() && TokenType.WHITE_SPACE == iterator.getTokenType()) {
        iterator.retreat();
      }
      boolean afterArrow = !iterator.atEnd() && iterator.getTokenType() == mCLOSABLE_BLOCK_OP;
      if (afterArrow) {
        originalHandler.execute(editor, dataContext);
        PsiDocumentManager.getInstance(project).commitDocument(document);
        CodeStyleManager.getInstance(project).adjustLineIndent(file, caretModel.getOffset());
      }

      iterator = highlighter.createIterator(caretModel.getOffset());
      while (!iterator.atEnd() && TokenType.WHITE_SPACE == iterator.getTokenType()) {
        iterator.advance();
      }
      if (!iterator.atEnd() && mRCURLY == iterator.getTokenType()) {
        PsiDocumentManager.getInstance(project).commitDocument(document);
        final PsiElement element = file.findElementAt(iterator.getStart());
        if (element != null &&
            element.getNode().getElementType() == mRCURLY &&
            element.getParent() instanceof GrClosableBlock &&
            text.length() > caret && afterArrow) {
          return Result.DefaultForceIndent;
        }
      }
      if (afterArrow) {
        return Result.Stop;
      }

      if (editor.isInsertMode() &&
          !HandlerUtils.isReadOnly(editor) &&
          !editor.getSelectionModel().hasSelection() &&
          handleFlyingGeese(editor, caret, dataContext, originalHandler, file)) {
        return Result.DefaultForceIndent;
      }
    }

    if (handleEnter(editor, dataContext, project, originalHandler)) return Result.Stop;
    return Result.Continue;
  }

  protected static boolean handleEnter(Editor editor,
                                       DataContext dataContext,
                                       @NotNull Project project,
                                       EditorActionHandler originalHandler) {
    if (HandlerUtils.isReadOnly(editor)) {
      return false;
    }
    int caretOffset = editor.getCaretModel().getOffset();
    if (caretOffset < 1) return false;

    if (handleBetweenSquareBraces(editor, caretOffset, dataContext, project, originalHandler)) {
      return true;
    }
    if (handleInString(editor, caretOffset, dataContext, originalHandler)) {
      return true;
    }

    return false;
  }

  private static boolean handleFlyingGeese(Editor editor,
                                           int caretOffset,
                                           DataContext dataContext,
                                           EditorActionHandler originalHandler,
                                           PsiFile file) {
    Project project = CommonDataKeys.PROJECT.getData(dataContext);
    if (project == null) return false;

    GroovyCodeStyleSettings codeStyleSettings =
      CodeStyleSettingsManager.getSettings(project).getCustomSettings(GroovyCodeStyleSettings.class);
    if (!codeStyleSettings.USE_FLYING_GEESE_BRACES) return false;

    PsiElement element = file.findElementAt(caretOffset);
    if (element != null && element.getNode().getElementType() == TokenType.WHITE_SPACE) {
      element = GeeseUtil.getNextNonWhitespaceToken(element);
    }
    if (element == null || !GeeseUtil.isClosureRBrace(element)) return false;

    element = GeeseUtil.getNextNonWhitespaceToken(element);
    if (element == null || element.getNode().getElementType() != mNLS || StringUtil.countChars(element.getText(), '\n') > 1) {
      return false;
    }

    element = GeeseUtil.getNextNonWhitespaceToken(element);
    if (element == null || !GeeseUtil.isClosureRBrace(element)) return false;

    Document document = editor.getDocument();
    PsiDocumentManager.getInstance(project).commitDocument(document);

    int toRemove = element.getTextRange().getStartOffset();
    document.deleteString(caretOffset + 1, toRemove);

    originalHandler.execute(editor, dataContext);

    String text = document.getText();
    int nextLineFeed = text.indexOf('\n', caretOffset + 1);
    if (nextLineFeed == -1) nextLineFeed = text.length();
    CodeStyleManager.getInstance(project).reformatText(file, caretOffset, nextLineFeed);

    return true;
  }

  private static boolean handleBetweenSquareBraces(Editor editor,
                                                   int caret,
                                                   DataContext context,
                                                   Project project,
                                                   EditorActionHandler originalHandler) {
    String text = editor.getDocument().getText();
    if (text == null || text.length() == 0) return false;
    final EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
    if (caret < 1 || caret > text.length() - 1) {
      return false;
    }
    HighlighterIterator iterator = highlighter.createIterator(caret - 1);
    if (mLBRACK == iterator.getTokenType()) {
      if (text.length() > caret) {
        iterator = highlighter.createIterator(caret);
        if (mRBRACK == iterator.getTokenType()) {
          originalHandler.execute(editor, context);
          originalHandler.execute(editor, context);
          editor.getCaretModel().moveCaretRelatively(0, -1, false, false, true);
          insertSpacesByGroovyContinuationIndent(editor, project);
          return true;
        }
      }
    }
    return false;
  }

  private static boolean handleInString(Editor editor, int caretOffset, DataContext dataContext, EditorActionHandler originalHandler) {
    Project project = CommonDataKeys.PROJECT.getData(dataContext);
    if (project == null) return false;

    final VirtualFile vfile = FileDocumentManager.getInstance().getFile(editor.getDocument());
    assert vfile != null;
    PsiFile file = PsiManager.getInstance(project).findFile(vfile);

    Document document = editor.getDocument();
    String fileText = document.getText();
    if (fileText.length() == caretOffset) return false;

    if (!checkStringApplicable(editor, caretOffset)) return false;
    if (file == null) return false;

    PsiDocumentManager.getInstance(project).commitDocument(document);

    final PsiElement stringElement = inferStringPair(file, caretOffset);
    if (stringElement == null) return false;

    ASTNode node = stringElement.getNode();
    final IElementType nodeElementType = node.getElementType();

    boolean isInsertIndent = isInsertIndent(caretOffset, stringElement.getTextRange().getStartOffset(), fileText);

    // For simple String literals like 'abcdef'
    CaretModel caretModel = editor.getCaretModel();
    if (nodeElementType == mSTRING_LITERAL) {
      if (isSingleQuoteString(stringElement)) {

        //the case of print '\<caret>'
        if (isSlashBeforeCaret(caretOffset, fileText)) {
          EditorModificationUtil.insertStringAtCaret(editor, "\n");
        }
        else if(stringElement.getParent() instanceof GrReferenceExpression) {
          TextRange range = stringElement.getTextRange();
          convertEndToMultiline(range.getEndOffset(), document, fileText, '\'');
          document.insertString(range.getStartOffset(), "''");
          caretModel.moveToOffset(caretOffset + 2);
          EditorModificationUtil.insertStringAtCaret(editor, "\n");
        }
        else {
          EditorModificationUtil.insertStringAtCaret(editor, "'+");
          originalHandler.execute(editor, dataContext);
          EditorModificationUtil.insertStringAtCaret(editor, "'");
          PsiDocumentManager.getInstance(project).commitDocument(document);
          CodeStyleManager.getInstance(project).reformatRange(file, caretOffset, caretModel.getOffset());
        }
      }
      else {
        insertLineFeedInString(editor, dataContext, originalHandler, isInsertIndent);
      }
      return true;
    }

    if (GSTRING_TOKENS.contains(nodeElementType) ||
        nodeElementType == GSTRING_CONTENT && GSTRING_TOKENS.contains(node.getFirstChildNode().getElementType()) ||
        nodeElementType == mDOLLAR && node.getTreeParent().getTreeParent().getElementType() == GSTRING) {
      PsiElement parent = stringElement.getParent();
      if (nodeElementType == mGSTRING_LITERAL) {
        parent = stringElement;
      }
      else {
        while (parent != null && !(parent instanceof GrLiteral)) {
          parent = parent.getParent();
        }
      }
      if (parent == null) return false;
      if (isDoubleQuotedString(parent)) {
        PsiElement exprSibling = stringElement.getNextSibling();
        boolean rightFromDollar = exprSibling instanceof GrExpression && exprSibling.getTextRange().getStartOffset() == caretOffset;
        if (rightFromDollar) caretOffset--;
        TextRange parentRange = parent.getTextRange();
        if (rightFromDollar || parent.getParent() instanceof GrReferenceExpression) {
          convertEndToMultiline(parent.getTextRange().getEndOffset(), document, fileText, '"');
          document.insertString(parentRange.getStartOffset(), "\"\"");
          caretModel.moveToOffset(caretOffset + 2);
          EditorModificationUtil.insertStringAtCaret(editor, "\n");
          if (rightFromDollar) {
            caretModel.moveCaretRelatively(1, 0, false, false, true);
          }
        }
        else if (isSlashBeforeCaret(caretOffset, fileText)) {
          EditorModificationUtil.insertStringAtCaret(editor, "\n");
        }
        else {
          EditorModificationUtil.insertStringAtCaret(editor, "\"+");
          originalHandler.execute(editor, dataContext);
          EditorModificationUtil.insertStringAtCaret(editor, "\"");
          PsiDocumentManager.getInstance(project).commitDocument(document);
          CodeStyleManager.getInstance(project).reformatRange(file, caretOffset, caretModel.getOffset());
        }
      }
      else {
        insertLineFeedInString(editor, dataContext, originalHandler, isInsertIndent);
      }
      return true;
    }

    if (REGEX_TOKENS.contains(nodeElementType) ||
        nodeElementType == GSTRING_CONTENT && REGEX_TOKENS.contains(node.getFirstChildNode().getElementType()) ||
        nodeElementType == mDOLLAR && node.getTreeParent().getTreeParent().getElementType() == REGEX) {
      PsiElement parent = stringElement.getParent();
      if (nodeElementType == mREGEX_LITERAL || nodeElementType == mDOLLAR_SLASH_REGEX_LITERAL) {
        parent = stringElement;
      }
      else {
        while (parent != null && !(parent instanceof GrLiteral)) {
          parent = parent.getParent();
        }
      }
      if (parent == null || parent.getLastChild() instanceof PsiErrorElement) return false;
      PsiElement exprSibling = stringElement.getNextSibling();
      boolean rightFromDollar = exprSibling instanceof GrExpression && exprSibling.getTextRange().getStartOffset() == caretOffset;
      if (rightFromDollar) {
        caretModel.moveToOffset(caretOffset - 1);
      }
      insertLineFeedInString(editor, dataContext, originalHandler, isInsertIndent);
      if (rightFromDollar) {
        caretModel.moveCaretRelatively(1, 0, false, false, true);
      }
      return true;
    }

    return false;
  }

  private static boolean isDoubleQuotedString(PsiElement element) {
    return "\"".equals(GrStringUtil.getStartQuote(element.getText()));
  }

  private static boolean isSingleQuoteString(PsiElement element) {
    return "'".equals(GrStringUtil.getStartQuote(element.getText()));
  }

  @Nullable
  private static PsiElement inferStringPair(PsiFile file, int caretOffset) {
    PsiElement stringElement = file.findElementAt(caretOffset - 1);
    if (stringElement == null) return null;
    ASTNode node = stringElement.getNode();
    if (node == null) return null;

    // For expression injection in GString like "abc ${}<caret>  abc"
    if (!INNER_STRING_TOKENS.contains(node.getElementType()) && checkGStringInjection(stringElement)) {
      stringElement = stringElement.getParent().getParent().getNextSibling();
      if (stringElement == null) return null;
    }

    return stringElement;
  }

  private static boolean isSlashBeforeCaret(int caretOffset, String fileText) {
    return caretOffset > 0 && fileText.charAt(caretOffset - 1) == '\\';
  }

  private static void insertLineFeedInString(Editor editor,
                                             DataContext dataContext,
                                             EditorActionHandler originalHandler,
                                             boolean isInsertIndent) {
    if (isInsertIndent) {
      originalHandler.execute(editor, dataContext);
    }
    else {
      EditorModificationUtil.insertStringAtCaret(editor, "\n");
    }
  }

  private static boolean isInsertIndent(int caret, int stringOffset, String text) {
    final int i = text.indexOf('\n', stringOffset);
    return stringOffset < i && i < caret;
  }

  private static void convertEndToMultiline(int caretOffset, Document document, String fileText, char c) {
    if (caretOffset < fileText.length() && fileText.charAt(caretOffset) == c ||
        caretOffset > 0 && fileText.charAt(caretOffset - 1) == c) {
      document.insertString(caretOffset, new CharArrayCharSequence(c, c));
    }
    else {
      document.insertString(caretOffset, new CharArrayCharSequence(c, c, c));
    }
  }

  private static boolean checkStringApplicable(Editor editor, int caret) {
    final GroovyLexer lexer = new GroovyLexer();
    lexer.start(editor.getDocument().getText());

    while (lexer.getTokenEnd() < caret) {
      lexer.advance();
    }
    final IElementType leftToken = lexer.getTokenType();
    if (lexer.getTokenEnd() <= caret) lexer.advance();
    final IElementType rightToken = lexer.getTokenType();

    if (!(ALL_STRINGS.contains(leftToken))) {
      return false;
    }
    if (BEFORE_DOLLAR.contains(leftToken) && !AFTER_DOLLAR.contains(rightToken)) {
      return false;
    }
    if (EXPR_END.contains(leftToken) && !AFTER_EXPR_END.contains(rightToken)) {
      return false;
    }
    if (STRING_END.contains(leftToken) && !STRING_END.contains(rightToken)) {
      return false;
    }
    return true;
  }

  private static boolean checkGStringInjection(PsiElement element) {
    if (element != null && (element.getParent() instanceof GrReferenceExpression || element.getParent() instanceof GrClosableBlock)) {
      final PsiElement parent = element.getParent().getParent();
      if (!(parent instanceof GrStringInjection)) return false;
      PsiElement nextSibling = parent.getNextSibling();
      if (nextSibling == null) return false;
      return INNER_STRING_TOKENS.contains(nextSibling.getNode().getElementType());
    }
    return false;
  }
}
