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

import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.Separators;
import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers.Modifiers;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.*;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.constructor.ConstructorBody;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.declaration.Declaration;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.AssignmentExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.ConditionalExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.ExpressionStatement;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.imports.ImportStatement;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.TypeDefinition;
import org.jetbrains.plugins.groovy.lang.parser.parsing.toplevel.CompilationUnit;
import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;

/**
 * Parser for Groovy script files
 *
 * @author ilyas, Dmitry.Krasilschikov
 */
public class GroovyParser implements PsiParser {

  public static final TokenSet RCURLY_ONLY = TokenSet.create(GroovyTokenTypes.mRCURLY);
  public static final TokenSet CASE_SECTION_END = TokenSet.create(GroovyTokenTypes.kCASE, GroovyTokenTypes.kDEFAULT,
                                                                  GroovyTokenTypes.mRCURLY);

  public boolean parseDeep() {
    return false;
  }

  public static void parseExpression(PsiBuilder builder) {
    ExpressionStatement.argParse(builder, new GroovyParser());
  }

  @Override
  @NotNull
  public ASTNode parse(IElementType root, PsiBuilder builder) {
    //builder.setDebugMode(true);
    if (root == GroovyElementTypes.OPEN_BLOCK) {
      OpenOrClosableBlock.parseOpenBlockDeep(builder, this);
    }
    else if (root == GroovyElementTypes.CLOSABLE_BLOCK) {
      OpenOrClosableBlock.parseClosableBlockDeep(builder, this);
    }
    else if (root == GroovyElementTypes.CONSTRUCTOR_BODY) {
      ConstructorBody.parseConstructorBodyDeep(builder, this);
    }
    else {
      assert root == GroovyParserDefinition.GROOVY_FILE : root;
      PsiBuilder.Marker rootMarker = builder.mark();
      CompilationUnit.parseFile(builder, this);
      rootMarker.done(root);
    }
    return builder.getTreeBuilt();
  }

  public boolean parseForStatement(PsiBuilder builder) {
    PsiBuilder.Marker marker = builder.mark();

    ParserUtils.getToken(builder, GroovyTokenTypes.kFOR);
    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mLPAREN, GroovyBundle.message("lparen.expected"))) {
      marker.done(GroovyElementTypes.FOR_STATEMENT);
      return true;
    }
    if (!ForStatement.forClauseParse(builder, this)) {
      builder.error(GroovyBundle.message("for.clause.expected"));
      marker.done(GroovyElementTypes.FOR_STATEMENT);
      return true;
    }

    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);

    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mRPAREN, GroovyBundle.message("rparen.expected"))) {
      ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);
      marker.done(GroovyElementTypes.FOR_STATEMENT);
      return true;
    }

    PsiBuilder.Marker warn = builder.mark();
    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);

    if (parseExtendedStatement(builder)) {
      warn.rollbackTo();
      marker.done(GroovyElementTypes.FOR_STATEMENT);
      return true;
    }

    if (parseStatement(builder, true)) {
      warn.drop();
    }
    else {
      warn.rollbackTo();
      builder.error(GroovyBundle.message("statement.expected"));
    }
    marker.done(GroovyElementTypes.FOR_STATEMENT);
    return true;
  }

  public boolean parseIfStatement(PsiBuilder builder) {
    //allow error messages
    PsiBuilder.Marker ifStmtMarker = builder.mark();
    if (!ParserUtils.getToken(builder, GroovyTokenTypes.kIF)) {
      ifStmtMarker.rollbackTo();
      builder.error(GroovyBundle.message("if.expected"));
      return false;
    }

    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mLPAREN, GroovyBundle.message("lparen.expected"))) {
      ifStmtMarker.done(GroovyElementTypes.IF_STATEMENT);
      return true;
    }

    if (!ConditionalExpression.parse(builder, this)) {
      builder.error(GroovyBundle.message("expression.expected"));
    }

    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);
    ParserUtils.getToken(builder, GroovyTokenTypes.mRPAREN, GroovyBundle.message("rparen.expected"));

    if (!parseBranch(builder)) {
      ifStmtMarker.done(GroovyElementTypes.IF_STATEMENT);
      return true;
    }

    PsiBuilder.Marker rb = builder.mark();
    if (GroovyTokenTypes.kELSE.equals(builder.getTokenType()) ||
        (Separators.parse(builder) && builder.getTokenType() == GroovyTokenTypes.kELSE)) {
      rb.drop();
      ParserUtils.getToken(builder, GroovyTokenTypes.kELSE);

      parseBranch(builder);
    }
    else {
      rb.rollbackTo();
    }

    ifStmtMarker.done(GroovyElementTypes.IF_STATEMENT);
    return true;
  }

  public void parseSwitchCaseList(PsiBuilder builder) {
    if (parseGenericStatement(builder, CASE_SECTION_END)) {
      parseCodeBlock(builder, CASE_SECTION_END);
    }
  }

  //gsp directives, scriptlets and such
  protected boolean isExtendedSeparator(@Nullable final IElementType tokenType) {
    return false;
  }

  //gsp template statement, for example
  protected boolean parseExtendedStatement(PsiBuilder builder) {
    return false;
  }

  public boolean parseWhileStatement(PsiBuilder builder) {

    PsiBuilder.Marker marker = builder.mark();

    ParserUtils.getToken(builder, GroovyTokenTypes.kWHILE);

    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mLPAREN, GroovyBundle.message("lparen.expected"))) {
      marker.done(GroovyElementTypes.WHILE_STATEMENT);
      return true;
    }

    if (!ExpressionStatement.argParse(builder, this)) {
      builder.error(GroovyBundle.message("expression.expected"));
    }

    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);

    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mRPAREN, GroovyBundle.message("rparen.expected"))) {
      marker.done(GroovyElementTypes.WHILE_STATEMENT);
      return true;
    }

    parseBranch(builder);
    marker.done(GroovyElementTypes.WHILE_STATEMENT);
    return true;
  }

  private boolean parseBranch(@NotNull PsiBuilder builder) {
    PsiBuilder.Marker warn = builder.mark();
    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);

    if (!parseStatement(builder, true) && !parseExtendedStatement(builder)) {
      warn.rollbackTo();
      builder.error(GroovyBundle.message("statement.expected"));
      return false;
    }
    else {
      warn.drop();
      return true;
    }
  }

  public void parseBlockBody(PsiBuilder builder) {
    skipSeparators(builder);
    parseBlockBodyWithoutSkippingSeparators(builder);
  }

  public void parseBlockBodyWithoutSkippingSeparators(PsiBuilder builder) {
    parseCodeBlock(builder, RCURLY_ONLY);
    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);
  }

  private void parseCodeBlock(PsiBuilder builder, TokenSet until) {
    while (true) {
      if (builder.eof() || until.contains(builder.getTokenType())) break;
      if (!parseGenericStatement(builder, until)) break;
    }
  }

  private boolean parseGenericStatement(PsiBuilder builder, TokenSet until) {
    boolean plainStatement = parseStatement(builder, false);

    if (plainStatement || parseExtendedStatement(builder)) {
      if (parseSeparatorsWithoutLastNls(builder, plainStatement, until)) {
        return false;
      }
    }
    else {
      builder.error(GroovyBundle.message("wrong.statement"));
      assert builder.getTokenType() != GroovyTokenTypes.mLCURLY && builder.getTokenType() != GroovyTokenTypes.mRCURLY;
      builder.advanceLexer();
    }
    return true;
  }

  private boolean parseSeparatorsWithoutLastNls(PsiBuilder builder, boolean requireSeparator, TokenSet until) {
    boolean hasSeparator = false;
    while (true) {
      while (builder.getTokenType() == GroovyTokenTypes.mSEMI || isExtendedSeparator(builder.getTokenType())) {
        hasSeparator = true;
        builder.advanceLexer();
      }

      if (builder.getTokenType() == GroovyTokenTypes.mNLS) {
        PsiBuilder.Marker beforeNls = builder.mark();
        hasSeparator = true;
        builder.advanceLexer();
        if (builder.eof() || until.contains(builder.getTokenType())) {
          beforeNls.rollbackTo();
          return true;
        }
        beforeNls.drop();
      }
      else {
        break;
      }
    }
    if (builder.eof() || until.contains(builder.getTokenType())) {
      return true;
    }
    if (requireSeparator && !hasSeparator) {
      builder.error(GroovyBundle.message("separator.or.rcurly.expected"));
    }
    return false;
  }

  private boolean skipSeparators(PsiBuilder builder) {
    boolean hasSeparators = false;
    while (builder.getTokenType() == GroovyTokenTypes.mSEMI || isExtendedSeparator(builder.getTokenType()) || builder.getTokenType() ==
                                                                                                              GroovyTokenTypes.mNLS) {
      hasSeparators = true;
      builder.advanceLexer();
    }
    return hasSeparators;
  }

  public boolean parseStatement(PsiBuilder builder, boolean isBlockStatementNeeded) {
    if (isBlockStatementNeeded && GroovyTokenTypes.mLCURLY.equals(builder.getTokenType())) {
      final PsiBuilder.Marker marker = builder.mark();
      OpenOrClosableBlock.parseOpenBlockDeep(builder, this);
      marker.done(GroovyElementTypes.BLOCK_STATEMENT);
      return true;
    }

    if (isBlockStatementNeeded && GroovyTokenTypes.mSEMI == builder.getTokenType()) {
      return true;
    }

    if (GroovyTokenTypes.kIMPORT.equals(builder.getTokenType())) {
      PsiBuilder.Marker marker = builder.mark();
      ImportStatement.parse(builder, this);
      marker.error(GroovyBundle.message("import.not.allowed"));
      return true;
    }

    if (GroovyTokenTypes.kIF.equals(builder.getTokenType())) {
      return parseIfStatement(builder);
    }
    if (GroovyTokenTypes.kSWITCH.equals(builder.getTokenType())) {
      SwitchStatement.parseSwitch(builder, this);
      return true;
    }
    if (GroovyTokenTypes.kTRY.equals(builder.getTokenType())) {
      return TryCatchStatement.parse(builder, this);
    }
    if (GroovyTokenTypes.kWHILE.equals(builder.getTokenType())) {
      return parseWhileStatement(builder);
    }
    if (GroovyTokenTypes.kFOR.equals(builder.getTokenType())) {
      return parseForStatement(builder);
    }
    if (ParserUtils.lookAhead(builder, GroovyTokenTypes.kSYNCHRONIZED, GroovyTokenTypes.mLPAREN)) {
      PsiBuilder.Marker synMarker = builder.mark();
      if (SynchronizedStatement.parse(builder, this)) {
        synMarker.drop();
        return true;
      }
      else {
        synMarker.rollbackTo();
      }
    }

    // Possible errors
    if (GroovyTokenTypes.kELSE.equals(builder.getTokenType())) {
      ParserUtils.wrapError(builder, GroovyBundle.message("else.without.if"));
      parseStatement(builder, true);
      return true;
    }
    if (GroovyTokenTypes.kCATCH.equals(builder.getTokenType())) {
      ParserUtils.wrapError(builder, GroovyBundle.message("catch.without.try"));
      parseStatement(builder, false);
      return true;
    }
    if (GroovyTokenTypes.kFINALLY.equals(builder.getTokenType())) {
      ParserUtils.wrapError(builder, GroovyBundle.message("finally.without.try"));
      parseStatement(builder, false);
      return true;
    }
    if (GroovyTokenTypes.kCASE.equals(builder.getTokenType())) {
      PsiBuilder.Marker marker = builder.mark();
      SwitchStatement.parseCaseLabel(builder, this);
      marker.error(GroovyBundle.message("case.without.switch"));
      parseStatement(builder, false);
      return true;
    }
    if (GroovyTokenTypes.kDEFAULT.equals(builder.getTokenType())) {
      PsiBuilder.Marker marker = builder.mark();
      SwitchStatement.parseCaseLabel(builder, this);
      marker.error(GroovyBundle.message("default.without.switch"));
      parseStatement(builder, false);
      return true;
    }

    if (BranchStatement.BRANCH_KEYWORDS.contains(builder.getTokenType())) {
      return BranchStatement.parse(builder, this);
    }
    if (parseLabeledStatement(builder)) {
      return true;
    }

    if (parseDeclaration(builder, false, false, null)) return true;

    return AssignmentExpression.parse(builder, this, true);
  }

  /**
   * parses imports (marks them as not allowed), type definitions, methods, variables or fields (if isInClass), initializers (if isInClass), constructors
   * with corresponding typeDefinitionName
   * <p/>
   * If non of preceding elements was found rolls back and return false
   */
  public boolean parseDeclaration(@NotNull PsiBuilder builder,
                                  boolean isInClass,
                                  boolean isInAnnotation,
                                  @Nullable String typeDefinitionName) {
    PsiBuilder.Marker declMarker = builder.mark();
    boolean modifiersParsed = Modifiers.parse(builder, this);

    if (GroovyTokenTypes.kIMPORT == builder.getTokenType()) {
      final PsiBuilder.Marker impMarker = declMarker.precede();
      ImportStatement.parseAfterModifiers(builder);
      declMarker.done(GroovyElementTypes.IMPORT_STATEMENT);
      impMarker.error(GroovyBundle.message("import.not.allowed"));
      return true;
    }

    if (isTypeDefinitionStart(builder)) {
      final IElementType tdType = TypeDefinition.parseAfterModifiers(builder, this);
      if (tdType != GroovyElementTypes.WRONGWAY) {
        declMarker.done(tdType);
      }
      else {
        builder.error(GroovyBundle.message("identifier.expected"));
        declMarker.drop();
      }
      return true;
    }

    if (isInClass && parseInitializer(builder)) {
      declMarker.done(GroovyElementTypes.CLASS_INITIALIZER);
      return true;
    }

    final IElementType declType =
      Declaration.parseAfterModifiers(builder, isInClass, isInAnnotation, typeDefinitionName, this, modifiersParsed);
    if (declType != GroovyElementTypes.WRONGWAY) {
      if (declType != null) {
        declMarker.done(declType);
      }
      else {
        declMarker.drop();
      }
      return true;
    }

    if (modifiersParsed) {
      declMarker.drop();
      builder.error(GroovyBundle.message("identifier.expected"));
      return true;
    }

    declMarker.rollbackTo();
    return false;
  }

  private boolean parseInitializer(PsiBuilder builder) {
    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);
    return GroovyTokenTypes.mLCURLY == builder.getTokenType() && OpenOrClosableBlock.parseOpenBlock(builder, this);
  }

  private static boolean isTypeDefinitionStart(PsiBuilder builder) {
    return GroovyTokenTypes.kCLASS == builder.getTokenType() ||               //class
           GroovyTokenTypes.kINTERFACE == builder.getTokenType() ||           //interface
           GroovyTokenTypes.kENUM == builder.getTokenType() ||                //enum
           GroovyTokenTypes.kTRAIT == builder.getTokenType() ||               //trait
           ParserUtils.lookAhead(builder, GroovyTokenTypes.mAT, GroovyTokenTypes.kINTERFACE);  //@interface
  }

  public boolean parseStatementWithImports(PsiBuilder builder) {
    if (ImportStatement.parse(builder, this)) {
      return true;
    }
    else {
      return parseStatement(builder, false);
    }
  }

  private boolean parseLabeledStatement(PsiBuilder builder) {

    PsiBuilder.Marker marker = builder.mark();

    if (!ParserUtils.getToken(builder, GroovyTokenTypes.mIDENT) || !ParserUtils.getToken(builder, GroovyTokenTypes.mCOLON)) {
      marker.rollbackTo();
      return false;
    }

    final PsiBuilder.Marker nlsMarker = builder.mark();

    ParserUtils.getToken(builder, GroovyTokenTypes.mNLS);
    if (parseStatement(builder, true)) {
      nlsMarker.drop();
    }
    else {
      nlsMarker.rollbackTo();
      builder.error(GroovyBundle.message("statement.expected"));
    }

    marker.done(GroovyElementTypes.LABELED_STATEMENT);
    return true;
  }
}
