/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.json;

import com.facebook.buck.util.Ansi;
import com.facebook.buck.util.InputStreamConsumer;
import com.facebook.buck.util.ProjectFilesystem;
import com.facebook.buck.util.environment.Platform;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Delegates to buck.py for parsing of buck build files.  Constructed on demand for the
 * parsing phase and must be closed afterward to free up resources.
 */
public class ProjectBuildFileParser implements AutoCloseable {
  /** Path to the buck.py script that is used to evaluate a build file. */
  private static final String PATH_TO_BUCK_PY = System.getProperty("buck.path_to_buck_py",
      "src/com/facebook/buck/parser/buck.py");

  private Process buckPyProcess;

  private BuildFileToJsonParser buckPyStdoutParser;
  private BufferedWriter buckPyStdinWriter;

  private final File projectRoot;
  private final ImmutableSet<String> ignorePaths;
  private final ImmutableList<String> commonIncludes;
  private final String pythonInterpreter;

  private boolean isServerMode;

  private boolean isInitialized;
  private boolean isClosed;

  public ProjectBuildFileParser(
      ProjectFilesystem projectFilesystem,
      Iterable<String> commonIncludes,
      String pythonInterpreter) {
    this.projectRoot = projectFilesystem.getProjectRoot();
    this.ignorePaths = projectFilesystem.getIgnorePaths();
    this.commonIncludes = ImmutableList.copyOf(commonIncludes);
    this.pythonInterpreter = Preconditions.checkNotNull(pythonInterpreter);

    // Default to server mode unless explicitly unset internally.
    setServerMode(true);
  }

  /**
   * Sets whether buck.py will use --server mode.  Server mode communicates via
   * stdin/stdout to accept new BUCK files to parse in a long running fashion.  It
   * also changes the stdout format so that output has an extra layer of structure
   * sufficient to communicate state and coordinate on individual BUCK files
   * submitted.
   * <p>
   * Note that you must not invoke this method after initialization.
   */
  private void setServerMode(boolean isServerMode) {
    ensureNotClosed();
    ensureNotInitialized();

    this.isServerMode = isServerMode;
  }

  private void ensureNotClosed() {
    Preconditions.checkState(!isClosed);
  }

  private void ensureNotInitialized() {
    Preconditions.checkState(!isInitialized);
  }

  /**
   * Initialization on demand moves around the performance impact of creating the Jython
   * interpreter to when parsing actually begins.  This makes it easier to attribute this time
   * to the actual parse phase.
   */
  private void initIfNeeded() throws IOException {
    ensureNotClosed();
    if (!isInitialized) {
      init();
      isInitialized = true;
    }
  }

  /**
   * Initialize the parser, starting buck.py.
   */
  private void init() throws IOException {
    ProcessBuilder processBuilder = new ProcessBuilder(buildArgs());
    buckPyProcess = processBuilder.start();

    OutputStream stdin = buckPyProcess.getOutputStream();
    InputStream stderr = buckPyProcess.getErrorStream();

    Thread stderrConsumer = new Thread(new InputStreamConsumer(stderr,
        System.err,
        new Ansi(Platform.detect())));
    stderrConsumer.start();

    buckPyStdinWriter = new BufferedWriter(new OutputStreamWriter(stdin));
  }

  private ImmutableList<String> buildArgs() {
    // Invoking buck.py and read JSON-formatted build rules from its stdout.
    ImmutableList.Builder<String> argBuilder = ImmutableList.builder();

    argBuilder.add(pythonInterpreter);

    // Ask python to unbuffer stdout so that we can coordinate based on the output as it is
    // produced.
    argBuilder.add("-u");

    argBuilder.add(PATH_TO_BUCK_PY);

    if (isServerMode) {
      // Provide BUCK files to parse via buck.py's stdin.
      argBuilder.add("--server");
    }

    argBuilder.add("--project_root", projectRoot.getAbsolutePath());

    // Add the --include flags.
    for (String include : commonIncludes) {
      argBuilder.add("--include");
      argBuilder.add(include);
    }

    for (String path : ignorePaths) {
      argBuilder.add("--ignore_path");
      argBuilder.add(path);
    }

    return argBuilder.build();
  }

  /**
   * Create, parse and destroy the parser in one step for an entire project.  This should
   * only be used when the tree must be parsed without a specific target to be built or
   * otherwise operated upon.
   */
  public static List<Map<String, Object>> getAllRulesInProject(
      ProjectBuildFileParserFactory factory,
      Iterable<String> includes)
      throws BuildFileParseException {
    try (ProjectBuildFileParser buildFileParser = factory.createParser(includes)) {
      buildFileParser.setServerMode(false);
      return buildFileParser.getAllRulesInternal(Optional.<String>absent());
    } catch (IOException e) {
      throw BuildFileParseException.createForGenericBuildFileParseError(e);
    }
  }

  /**
   * Collect all rules from a particular build file.
   *
   * @param buildFile should be an absolute path to a build file. Must have rootPath as its prefix.
   */
  public List<Map<String, Object>> getAllRules(String buildFile)
      throws BuildFileParseException {
    List<Map<String, Object>> result = getAllRulesAndMetaRules(buildFile);

    // Strip out the __includes meta rule, which is the last rule.
    return Collections.unmodifiableList(result.subList(0, result.size() - 1));
  }

  /**
   * Collect all rules from a particular build file, along with meta rules about the rules, for
   * example which build files the rules depend on.
   *
   * @param buildFile should be an absolute path to a build file. Must have rootPath as its prefix.
   */
  public List<Map<String, Object>> getAllRulesAndMetaRules(String buildFile)
      throws BuildFileParseException {
    try {
      return getAllRulesInternal(Optional.of(buildFile));
    } catch (IOException e) {
      throw BuildFileParseException.createForBuildFileParseError(buildFile, e);
    }
  }

  @VisibleForTesting
  protected List<Map<String, Object>> getAllRulesInternal(Optional<String> buildFile)
      throws IOException {
    ensureNotClosed();
    initIfNeeded();

    // When in server mode, we require a build file.  When not in server mode, we
    // cannot accept a build file.  Pretty stupid, actually.  Consider fixing this.
    Preconditions.checkState(buildFile.isPresent() == isServerMode);

    if (buildFile.isPresent()) {
      buckPyStdinWriter.write(buildFile.get());
      buckPyStdinWriter.newLine();
      buckPyStdinWriter.flush();
    }

    // Construct the parser lazily because Jackson expects that when the parser is made it is
    // safe to immediately begin reading from the underlying stream to detect the encoding.
    // For our server use case, the server will produce no output until directed to by a
    // request for a particular build file.
    //
    // TODO: Jackson has a severe bug which assumes that it is safe to require at least 4 bytes
    // of input due to JSON's BOM concept (see detectEncoding).  buck.py, and many other
    // facilities, do not write a BOM header and therefore may end up producing insufficient
    // bytes to unwedge the parser's construction.  For example, if the first BUCK file
    // submitted outputted no rules (that is, "[]"), then this line would hang waiting for
    // more input!
    if (buckPyStdoutParser == null) {
      buckPyStdoutParser = new BuildFileToJsonParser(buckPyProcess.getInputStream());
    }

    return buckPyStdoutParser.nextRules();
  }

  @Override
  @SuppressWarnings("PMD.EmptyCatchBlock")
  public void close() throws BuildFileParseException {
    if (isClosed) {
      return;
    }

    try {
      if (isInitialized) {
        if (isServerMode) {
          // Allow buck.py to terminate gracefully.
          try {
            buckPyStdinWriter.close();
          } catch (IOException e) {
            // Safe to ignore since we've already flushed everything we wanted
            // to write.
          }
        }

        try {
          int exitCode = buckPyProcess.waitFor();
          if (exitCode != 0) {
            BuildFileParseException.createForUnknownParseError(
                String.format("Parser did not exit cleanly (exit code: %d)", exitCode));
          }
        } catch (InterruptedException e) {
          throw Throwables.propagate(e);
        }
      }
    } finally {
      isClosed = true;
    }
  }
}
