/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.base.lang.buildfile.parser;

import com.google.common.collect.ImmutableSet;
import com.google.idea.blaze.base.lang.buildfile.lexer.TokenKind;
import com.google.idea.blaze.base.lang.buildfile.psi.BuildElementTypes;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.tree.IElementType;

/** For parsing statements in BUILD files. */
public class StatementParsing extends Parsing {

  private static final ImmutableSet<TokenKind> STATEMENT_TERMINATOR_SET =
      ImmutableSet.of(TokenKind.EOF, TokenKind.NEWLINE, TokenKind.SEMI);

  public StatementParsing(ParsingContext context) {
    super(context);
  }

  /** Called at the start of parsing. Parses an entire file */
  public void parseFileInput() {
    builder.setDebugMode(ApplicationManager.getApplication().isUnitTestMode());
    while (!builder.eof()) {
      if (matches(TokenKind.NEWLINE)) {
        continue;
      }
      parseTopLevelStatement();
    }
  }

  // Unlike in Python grammar, 'load' and 'def' are only allowed as a top-level statement
  public void parseTopLevelStatement() {
    if (currentToken() == TokenKind.LOAD) {
      parseLoadStatement();
    } else if (currentToken() == TokenKind.DEF) {
      parseFunctionDefStatement();
    } else {
      parseStatement();
    }
  }

  // simple_stmt | compound_stmt
  public void parseStatement() {
    TokenKind current = currentToken();
    if (current == TokenKind.IF) {
      parseIfStatement();
    } else if (current == TokenKind.FOR) {
      parseForStatement();
    } else if (FORBIDDEN_KEYWORDS.contains(current)) {
      PsiBuilder.Marker mark = builder.mark();
      syncTo(STATEMENT_TERMINATOR_SET);
      mark.error(forbiddenKeywordError(current));
      builder.advanceLexer();
    } else {
      parseSimpleStatement();
    }
  }

  // func_def_stmt ::= DEF IDENTIFIER funcall_suffix ':' suite
  private void parseFunctionDefStatement() {
    PsiBuilder.Marker marker = builder.mark();
    expect(TokenKind.DEF);
    getExpressionParser().expectIdentifier("expected a function name");
    PsiBuilder.Marker listMarker = builder.mark();
    expect(TokenKind.LPAREN);
    getExpressionParser().parseFunctionParameters();
    expect(TokenKind.RPAREN, true);
    listMarker.done(BuildElementTypes.PARAMETER_LIST);
    expect(TokenKind.COLON);
    parseSuite();
    marker.done(BuildElementTypes.FUNCTION_STATEMENT);
  }

  // load '(' STRING (',' [IDENTIFIER '='] STRING)* [','] ')'
  private void parseLoadStatement() {
    PsiBuilder.Marker marker = builder.mark();
    expect(TokenKind.LOAD);
    expect(TokenKind.LPAREN);
    parseStringLiteral(false);
    // Not implementing [IDENTIFIER EQUALS] option -- not a documented feature,
    // so wait for users to complain
    boolean hasSymbols = false;
    while (!matches(TokenKind.RPAREN) && !matchesAnyOf(STATEMENT_TERMINATOR_SET)) {
      expect(TokenKind.COMMA);
      if (matches(TokenKind.RPAREN) || matchesAnyOf(STATEMENT_TERMINATOR_SET)) {
        break;
      }
      hasSymbols |= parseLoadedSymbol();
    }
    if (!hasSymbols) {
      builder.error("'load' statements must include at least one loaded function");
    }
    marker.done(BuildElementTypes.LOAD_STATEMENT);
  }

  /** [IDENTIFIER '='] STRING */
  private boolean parseLoadedSymbol() {
    PsiBuilder.Marker marker = builder.mark();
    if (currentToken() == TokenKind.STRING) {
      parseStringLiteral(true);
      marker.done(BuildElementTypes.LOADED_SYMBOL);
      return true;
    }
    if (parseAlias()) {
      marker.done(BuildElementTypes.LOADED_SYMBOL);
      return true;
    }
    marker.drop();
    builder.error("Expected a loaded symbol or alias");
    syncPast(ExpressionParsing.EXPR_TERMINATOR_SET);
    return false;
  }

  private boolean parseAlias() {
    if (!atTokenSequence(TokenKind.IDENTIFIER, TokenKind.EQUALS, TokenKind.STRING)) {
      return false;
    }
    PsiBuilder.Marker assignment = builder.mark();
    buildTokenElement(BuildElementTypes.TARGET_EXPRESSION);
    expect(TokenKind.EQUALS);
    parseStringLiteral(true);
    assignment.done(BuildElementTypes.ASSIGNMENT_STATEMENT);
    return true;
  }

  /** if_stmt ::= IF expr ':' suite (ELIF expr ':' suite)* [ELSE ':' suite] */
  private void parseIfStatement() {
    PsiBuilder.Marker marker = builder.mark();
    parseIfStatementPart(TokenKind.IF, BuildElementTypes.IF_PART, true);
    while (currentToken() == TokenKind.ELIF) {
      parseIfStatementPart(TokenKind.ELIF, BuildElementTypes.ELSE_IF_PART, true);
    }
    if (currentToken() == TokenKind.ELSE) {
      parseIfStatementPart(TokenKind.ELSE, BuildElementTypes.ELSE_PART, false);
    }
    marker.done(BuildElementTypes.IF_STATEMENT);
  }

  // cond_stmts ::= [EL]IF expr ':' suite
  private void parseIfStatementPart(TokenKind tokenKind, IElementType type, boolean conditional) {
    PsiBuilder.Marker marker = builder.mark();
    expect(tokenKind);
    if (conditional) {
      getExpressionParser().parseNonTupleExpression();
    }
    expect(TokenKind.COLON);
    parseSuite();
    marker.done(type);
  }

  // for_stmt ::= FOR IDENTIFIER IN expr ':' suite
  private void parseForStatement() {
    PsiBuilder.Marker marker = builder.mark();
    expect(TokenKind.FOR);
    getExpressionParser().parseForLoopVariables();
    expect(TokenKind.IN);
    getExpressionParser().parseExpression(false);
    expect(TokenKind.COLON);
    parseSuite();
    marker.done(BuildElementTypes.FOR_STATEMENT);
  }

  // simple_stmt ::= small_stmt (';' small_stmt)* ';'? NEWLINE
  private void parseSimpleStatement() {
    parseSmallStatementOrPass();
    while (matches(TokenKind.SEMI)) {
      if (matches(TokenKind.NEWLINE)) {
        return;
      }
      parseSmallStatementOrPass();
    }
    if (!builder.eof()) {
      expect(TokenKind.NEWLINE);
    }
  }

  // small_stmt | 'pass'
  private void parseSmallStatementOrPass() {
    if (currentToken() == TokenKind.PASS) {
      buildTokenElement(BuildElementTypes.PASS_STATMENT);
      return;
    }
    parseSmallStatement();
  }

  private void parseSmallStatement() {
    if (currentToken() == TokenKind.RETURN) {
      parseReturnStatement();
      return;
    }
    if (atAnyOfTokens(TokenKind.BREAK, TokenKind.CONTINUE)) {
      buildTokenElement(BuildElementTypes.FLOW_STATEMENT);
      return;
    }
    PsiBuilder.Marker refMarker = builder.mark();
    getExpressionParser().parseExpression(false);
    if (matches(TokenKind.EQUALS)) {
      getExpressionParser().parseExpression(false);
      refMarker.done(BuildElementTypes.ASSIGNMENT_STATEMENT);
    } else if (matchesAnyOf(TokenKind.AUGMENTED_ASSIGNMENT_OPS)) {
      getExpressionParser().parseExpression(false);
      refMarker.done(BuildElementTypes.AUGMENTED_ASSIGNMENT);
    } else {
      refMarker.drop();
    }
  }

  private void parseReturnStatement() {
    PsiBuilder.Marker marker = builder.mark();
    expect(TokenKind.RETURN);
    if (!STATEMENT_TERMINATOR_SET.contains(currentToken())) {
      getExpressionParser().parseExpression(false);
    }
    marker.done(BuildElementTypes.RETURN_STATEMENT);
  }

  // suite ::= simple_stmt | (NEWLINE INDENT stmt+ DEDENT)
  private void parseSuite() {
    if (!matches(TokenKind.NEWLINE)) {
      parseSimpleStatement();
      return;
    }
    PsiBuilder.Marker marker = builder.mark();
    if (expect(TokenKind.INDENT)) {
      while (!builder.eof() && !matches(TokenKind.DEDENT)) {
        parseStatement();
      }
    }
    marker.done(BuildElementTypes.STATEMENT_LIST);
  }
}
