// Copyright 2014 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.devtools.build.lib.syntax;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.HashCode;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.syntax.Parser.ParseResult;
import com.google.devtools.build.lib.syntax.SkylarkImport.SkylarkImportSyntaxException;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Abstract syntax node for an entire BUILD file.
 */
// TODO(bazel-team): Consider breaking this up into two classes: One that extends ASTNode and does
// not include import info; and one that wraps that object with additional import info but that
// does not itself extend ASTNode. This would help keep the AST minimalistic.
public class BuildFileAST extends ASTNode {

  private final ImmutableList<Statement> statements;

  private final ImmutableList<Comment> comments;

  @Nullable private final ImmutableList<SkylarkImport> imports;

  /**
   * Whether any errors were encountered during scanning or parsing.
   */
  private final boolean containsErrors;

  private final List<Event> octalEvents;

  @Nullable private final String contentHashCode;

  private BuildFileAST(
      ImmutableList<Statement> statements,
      boolean containsErrors,
      String contentHashCode,
      Location location,
      ImmutableList<Comment> comments,
      @Nullable ImmutableList<SkylarkImport> imports,
      List<Event> octalEvents) {
    this.statements = statements;
    this.containsErrors = containsErrors;
    this.contentHashCode = contentHashCode;
    this.comments = comments;
    this.setLocation(location);
    this.imports = imports;
    this.octalEvents = octalEvents;
  }

  private static BuildFileAST create(
      List<Statement> preludeStatements,
      ParseResult result,
      String contentHashCode,
      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
      EventHandler eventHandler,
      boolean allowImportInternal) {
    ImmutableList.Builder<Statement> statementsbuilder =
        ImmutableList.<Statement>builder().addAll(preludeStatements);

    if (allowImportInternal) {
      for (Statement stmt : result.statements) {
        if (stmt instanceof LoadStatement) {
          statementsbuilder.add(LoadStatement.allowLoadingOfInternalSymbols((LoadStatement) stmt));
        } else {
          statementsbuilder.add(stmt);
        }
      }
    } else {
      statementsbuilder.addAll(result.statements);
    }
    ImmutableList<Statement> statements = statementsbuilder.build();
    boolean containsErrors = result.containsErrors;
    Pair<Boolean, ImmutableList<SkylarkImport>> skylarkImports =
        fetchLoads(statements, repositoryMapping, eventHandler);
    containsErrors |= skylarkImports.first;
    return new BuildFileAST(
        statements,
        containsErrors,
        contentHashCode,
        result.location,
        ImmutableList.copyOf(result.comments),
        skylarkImports.second,
        result.octalEvents);
  }

  private static BuildFileAST create(
      List<Statement> preludeStatements,
      ParseResult result,
      String contentHashCode,
      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
      EventHandler eventHandler) {
    return create(
        preludeStatements, result, contentHashCode, repositoryMapping, eventHandler, false);
  }

  /**
   * Extract a subtree containing only statements from {@code firstStatement} (included) up to
   * {@code lastStatement} excluded.
   */
  public BuildFileAST subTree(int firstStatement, int lastStatement) {
    ImmutableList<Statement> statements = this.statements.subList(firstStatement, lastStatement);
    ImmutableList.Builder<SkylarkImport> imports = ImmutableList.builder();
    for (Statement stmt : statements) {
      if (stmt instanceof LoadStatement) {
        String str = ((LoadStatement) stmt).getImport().getValue();
        try {
          imports.add(SkylarkImport.create(str, /* repositoryMapping= */ ImmutableMap.of()));
        } catch (SkylarkImportSyntaxException e) {
          throw new IllegalStateException(
              "Cannot create SkylarkImport for '" + str + "'. This is an internal error.", e);
        }
      }
    }
    return new BuildFileAST(
        statements,
        containsErrors,
        null,
        this.statements.get(firstStatement).getLocation(),
        ImmutableList.of(),
        imports.build(),
        octalEvents);
  }

  /**
   * Collects all load statements. Returns a pair with a boolean saying if there were errors and the
   * imports that could be resolved.
   */
  private static Pair<Boolean, ImmutableList<SkylarkImport>> fetchLoads(
      List<Statement> statements,
      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
      EventHandler eventHandler) {
    ImmutableList.Builder<SkylarkImport> imports = ImmutableList.builder();
    boolean error = false;
    for (Statement stmt : statements) {
      if (stmt instanceof LoadStatement) {
        String importString = ((LoadStatement) stmt).getImport().getValue();
        try {
          imports.add(SkylarkImport.create(importString, repositoryMapping));
        } catch (SkylarkImportSyntaxException e) {
          eventHandler.handle(Event.error(stmt.getLocation(), e.getMessage()));
          error = true;
        }
      }
    }
    return Pair.of(error, imports.build());
  }

  /**
   * Returns true if any errors were encountered during scanning or parsing. If
   * set, clients should not rely on the correctness of the AST for builds or
   * BUILD-file editing.
   */
  public boolean containsErrors() {
    return containsErrors;
  }

  /**
   * Returns an (immutable, ordered) list of statements in this BUILD file.
   */
  public ImmutableList<Statement> getStatements() {
    return statements;
  }

  /**
   * Returns an (immutable, ordered) list of comments in this BUILD file.
   */
  public ImmutableList<Comment> getComments() {
    return comments;
  }

  /** Returns a list of loads in this BUILD file. */
  public ImmutableList<SkylarkImport> getImports() {
    Preconditions.checkNotNull(imports, "computeImports Should be called in parse* methods");
    return imports;
  }

  /** Returns a list of loads as strings in this BUILD file. */
  public ImmutableList<StringLiteral> getRawImports() {
    ImmutableList.Builder<StringLiteral> imports = ImmutableList.builder();
    for (Statement stmt : statements) {
      if (stmt instanceof LoadStatement) {
        imports.add(((LoadStatement) stmt).getImport());
      }
    }
    return imports.build();
  }

  /** Returns true if there was no error event. */
  public boolean replayLexerEvents(Environment env, EventHandler eventHandler) {
    if (env.getSemantics().incompatibleDisallowOldOctalNotation() && !octalEvents.isEmpty()) {
      Event.replayEventsOn(eventHandler, octalEvents);
      return false;
    }
    return true;
  }

  /**
   * Executes this build file in a given Environment.
   *
   * <p>If, for any reason, execution of a statement cannot be completed, an {@link EvalException}
   * is thrown by {@link Eval#exec(Statement)}. This exception is caught here and reported
   * through reporter and execution continues on the next statement. In effect, there is a
   * "try/except" block around every top level statement. Such exceptions are not ignored, though:
   * they are visible via the return value. Rules declared in a package containing any error
   * (including loading-phase semantical errors that cannot be checked here) must also be considered
   * "in error".
   *
   * <p>Note that this method will not affect the value of {@link #containsErrors()}; that refers
   * only to lexer/parser errors.
   *
   * @return true if no error occurred during execution.
   */
  public boolean exec(Environment env, EventHandler eventHandler) throws InterruptedException {
    boolean ok = true;
    if (!replayLexerEvents(env, eventHandler)) {
      return false;
    }
    for (Statement stmt : statements) {
      if (!execTopLevelStatement(stmt, env, eventHandler)) {
        ok = false;
      }
    }
    return ok;
  }

  /**
   * Executes tol-level statement of this build file in a given Environment.
   *
   * <p>If, for any reason, execution of a statement cannot be completed, an {@link EvalException}
   * is thrown by {@link Eval#exec(Statement)}. This exception is caught here and reported
   * through reporter. In effect, there is a
   * "try/except" block around every top level statement. Such exceptions are not ignored, though:
   * they are visible via the return value. Rules declared in a package containing any error
   * (including loading-phase semantical errors that cannot be checked here) must also be considered
   * "in error".
   *
   * <p>Note that this method will not affect the value of {@link #containsErrors()}; that refers
   * only to lexer/parser errors.
   *
   * @return true if no error occurred during execution.
   */

  public boolean execTopLevelStatement(Statement stmt, Environment env,
      EventHandler eventHandler) throws InterruptedException {
    try {
      Eval.fromEnvironment(env).exec(stmt);
      return true;
    } catch (EvalException e) {
      // Do not report errors caused by a previous parsing error, as it has already been
      // reported.
      if (e.isDueToIncompleteAST()) {
        return false;
      }
      // When the exception is raised from another file, report first the location in the
      // BUILD file (as it is the most probable cause for the error).
      Location exnLoc = e.getLocation();
      Location nodeLoc = stmt.getLocation();
      eventHandler.handle(Event.error(
          (exnLoc == null || !nodeLoc.getPath().equals(exnLoc.getPath())) ? nodeLoc : exnLoc,
          e.getMessage()));
      return false;
    }
  }

  @Override
  public void prettyPrint(Appendable buffer, int indentLevel) throws IOException {
    // Only statements are printed, not comments and processed import data.
    for (Statement stmt : statements) {
      stmt.prettyPrint(buffer, indentLevel);
    }
  }

  @Override
  public String toString() {
    return "<BuildFileAST with " + statements.size() + " statements>";
  }

  @Override
  public void accept(SyntaxTreeVisitor visitor) {
    visitor.visit(this);
  }

  /**
   * Parse the specified build file, returning its AST. All errors during scanning or parsing will
   * be reported to the reporter.
   */
  public static BuildFileAST parseBuildFile(
      ParserInputSource input,
      List<Statement> preludeStatements,
      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
      EventHandler eventHandler) {
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        preludeStatements, result, /* contentHashCode= */ null, repositoryMapping, eventHandler);
  }

  /**
   * Parse the specified build file, returning its AST. All load statements parsed that way will be
   * exempt from visibility restrictions. All errors during scanning or parsing will be reported to
   * the reporter.
   */
  public static BuildFileAST parseVirtualBuildFile(
      ParserInputSource input,
      List<Statement> preludeStatements,
      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
      EventHandler eventHandler) {
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        preludeStatements,
        result,
        /* contentHashCode= */ null,
        repositoryMapping,
        eventHandler,
        true);
  }

  public static BuildFileAST parseBuildFile(ParserInputSource input, EventHandler eventHandler) {
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        /* preludeStatements= */ ImmutableList.<Statement>of(),
        result,
        /* contentHashCode= */ null,
        /* repositoryMapping= */ ImmutableMap.of(),
        eventHandler);
  }

  public static BuildFileAST parseSkylarkFile(
      byte[] bytes, byte[] digest, PathFragment path, EventHandler eventHandler)
      throws IOException {
    ParserInputSource input = ParserInputSource.create(bytes, path);
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        /* preludeStatements= */ ImmutableList.of(),
        result,
        HashCode.fromBytes(digest).toString(),
        /* repositoryMapping= */ ImmutableMap.of(),
        eventHandler);
  }

  public static BuildFileAST parseSkylarkFile(ParserInputSource input, EventHandler eventHandler) {
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        /* preludeStatements= */ ImmutableList.<Statement>of(),
        result,
        /* contentHashCode= */ null,
        /* repositoryMapping= */ ImmutableMap.of(),
        eventHandler);
  }

  /**
   * Parse the specified non-build Skylark file but avoid the validation of the imports, returning
   * its AST. All errors during scanning or parsing will be reported to the reporter.
   *
   * <p>This method should not be used in Bazel code, since it doesn't validate that the imports are
   * syntactically valid.
   */
  public static BuildFileAST parseSkylarkFileWithoutImports(
      ParserInputSource input, EventHandler eventHandler) {
    ParseResult result = Parser.parseFile(input, eventHandler);
    return new BuildFileAST(
        ImmutableList.<Statement>builder()
            .addAll(ImmutableList.<Statement>of())
            .addAll(result.statements)
            .build(),
        result.containsErrors,
        /* contentHashCode= */ null,
        result.location,
        ImmutableList.copyOf(result.comments),
        /* imports= */ null,
        result.octalEvents);
  }

  /**
   * Run static checks on the AST.
   *
   * @return a new AST (or the same), with the containsErrors flag updated.
   */
  public BuildFileAST validate(Environment env, EventHandler eventHandler) {
    boolean valid = ValidationEnvironment.validateAst(env, statements, eventHandler);
    if (valid || containsErrors) {
      return this;
    }
    return new BuildFileAST(
        statements, true, contentHashCode, getLocation(), comments, imports, octalEvents);
  }

  public static BuildFileAST parseString(EventHandler eventHandler, String... content) {
    String str = Joiner.on("\n").join(content);
    ParserInputSource input = ParserInputSource.create(str, PathFragment.EMPTY_FRAGMENT);
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return create(
        /* preludeStatements= */ ImmutableList.of(),
        result,
        /* contentHashCode= */ null,
        /* repositoryMapping= */ ImmutableMap.of(),
        eventHandler);
  }

  /**
   * Parse the specified build file, without building the AST.
   *
   * @return true if the input file is syntactically valid
   */
  public static boolean checkSyntax(ParserInputSource input, EventHandler eventHandler) {
    Parser.ParseResult result = Parser.parseFile(input, eventHandler);
    return !result.containsErrors;
  }

  /**
   * Evaluates the code and return the value of the last statement if it's an
   * Expression or else null.
   */
  @Nullable public Object eval(Environment env) throws EvalException, InterruptedException {
    Object last = null;
    Eval evaluator = Eval.fromEnvironment(env);
    for (Statement statement : statements) {
      if (statement instanceof ExpressionStatement) {
        last = ((ExpressionStatement) statement).getExpression().eval(env);
      } else {
        evaluator.exec(statement);
        last = null;
      }
    }
    return last;
  }

  /**
   * Evaluates the lines from input and return the value of the last statement if it's an
   * Expression or else null. In case of error (either during validation or evaluation), it
   * throws an EvalException.
   */
  @Nullable
  public static Object eval(Environment env, String... input)
      throws EvalException, InterruptedException {
    BuildFileAST ast = parseAndValidateSkylarkString(env, input);
    return ast.eval(env);
  }

  /**
   * Parses and validates the lines from input and return the AST In case of error during
   * validation, it throws an EvalException.
   */
  public static BuildFileAST parseAndValidateSkylarkString(Environment env, String[] input)
      throws EvalException {
    BuildFileAST ast = parseString(env.getEventHandler(), input);
    ValidationEnvironment.validateAst(env, ast.getStatements());
    return ast;
  }

  /**
   * Returns a hash code calculated from the string content of the source file of this AST.
   */
  @Nullable public String getContentHashCode() {
    return contentHashCode;
  }
}
