/*
 * 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.command;

import static com.facebook.buck.rules.BuildableProperties.Kind.ANDROID;
import static com.facebook.buck.rules.BuildableProperties.Kind.LIBRARY;
import static com.facebook.buck.rules.BuildableProperties.Kind.PACKAGING;

import com.facebook.buck.android.AndroidBinaryRule;
import com.facebook.buck.android.AndroidDexTransitiveDependencies;
import com.facebook.buck.android.AndroidLibraryRule;
import com.facebook.buck.android.AndroidResourceRule;
import com.facebook.buck.android.NdkLibrary;
import com.facebook.buck.java.JavaLibraryRule;
import com.facebook.buck.java.PrebuiltJarRule;
import com.facebook.buck.model.BuildFileTree;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.parser.PartialGraph;
import com.facebook.buck.rules.AbstractDependencyVisitor;
import com.facebook.buck.rules.AnnotationProcessingData;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.Buildable;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.ExportDependencies;
import com.facebook.buck.rules.JavaPackageFinder;
import com.facebook.buck.rules.ProjectConfigRule;
import com.facebook.buck.rules.SourceRoot;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.AndroidPlatformTarget;
import com.facebook.buck.util.Ansi;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.Console;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.KeystoreProperties;
import com.facebook.buck.util.ProcessExecutor;
import com.facebook.buck.util.ProjectFilesystem;
import com.facebook.buck.util.Verbosity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Files;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

import javax.annotation.Nullable;

/**
 * Utility to map the build files in a project built with Buck into a collection of metadata files
 * so that the project can be built with IntelliJ. This uses a number of heuristics specific to our
 * repository at Facebook that does not make this a generally applicable solution. Hopefully over
 * time, the Facebook-specific logic will be removed.
 */
public class Project {

  /**
   * This directory is analogous to the gen/ directory that IntelliJ would produce when building an
   * Android module. It contains files such as R.java, BuildConfig.java, and Manifest.java.
   * <p>
   * By default, IntelliJ generates its gen/ directories in our source tree, which would likely
   * mess with the user's use of {@code glob(['**&#x2f;*.java'])}. For this reason, we encourage
   * users to target
   */
  public static final String ANDROID_GEN_DIR = BuckConstant.BUCK_OUTPUT_DIRECTORY + "/android";

  /**
   * Prefix for build targets whose output will be in {@link #ANDROID_GEN_DIR}.
   */
  private static final String ANDROID_GEN_BUILD_TARGET_PREFIX =
      String.format("//%s/", ANDROID_GEN_DIR);

  /**
   * Path to the intellij.py script that is used to transform the JSON written by this file.
   */
  private static final String PATH_TO_INTELLIJ_PY = System.getProperty(
      "buck.path_to_intellij_py",
      // Fall back on this value when running Buck from an IDE.
      new File("src/com/facebook/buck/command/intellij.py").getAbsolutePath());

  /**
   * For now, do not write any project.properties files. We have failed to provide them in the
   * same format as IntelliJ itself would generate them. That means that IntelliJ overwrites our
   * generated versions at some point. The next time `buck project` is run, Buck overwrites them
   * again, which causes IntelliJ to go and index the world. Empirically, it seems that if we do
   * not write them at all, IntelliJ can live without them.
   */
  private static boolean GENERATE_PROPERTIES_FILES = false;

  private final PartialGraph partialGraph;
  private final BuildFileTree buildFileTree;
  private final ImmutableMap<String, String> basePathToAliasMap;
  private final JavaPackageFinder javaPackageFinder;
  private final ExecutionContext executionContext;
  private final ProjectFilesystem projectFilesystem;
  private final Optional<String> pathToDefaultAndroidManifest;
  private final Optional<String> pathToPostProcessScript;
  private final Set<PrebuiltJarRule> libraryJars;
  private final String pythonInterpreter;

  public Project(PartialGraph partialGraph,
      Map<String, String> basePathToAliasMap,
      JavaPackageFinder javaPackageFinder,
      ExecutionContext executionContext,
      ProjectFilesystem projectFilesystem,
      Optional<String> pathToDefaultAndroidManifest,
      Optional<String> pathToPostProcessScript,
      String pythonInterpreter) {
    this.partialGraph = Preconditions.checkNotNull(partialGraph);
    this.buildFileTree = new BuildFileTree(partialGraph.getTargets());
    this.basePathToAliasMap = ImmutableMap.copyOf(basePathToAliasMap);
    this.javaPackageFinder = Preconditions.checkNotNull(javaPackageFinder);
    this.executionContext = Preconditions.checkNotNull(executionContext);
    this.projectFilesystem = Preconditions.checkNotNull(projectFilesystem);
    this.pathToDefaultAndroidManifest = Preconditions.checkNotNull(pathToDefaultAndroidManifest);
    this.pathToPostProcessScript = Preconditions.checkNotNull(pathToPostProcessScript);
    this.libraryJars = Sets.newHashSet();
    this.pythonInterpreter = Preconditions.checkNotNull(pythonInterpreter);
  }

  public int createIntellijProject(File jsonTempFile,
      ProcessExecutor processExecutor,
      PrintStream stdOut,
      PrintStream stdErr) throws IOException {
    List<Module> modules = createModulesForProjectConfigs();
    writeJsonConfig(jsonTempFile, modules);

    List<String> modifiedFiles = Lists.newArrayList();

    // Process the JSON config to generate the .xml and .iml files for IntelliJ.
    ExitCodeAndOutput result = processJsonConfig(jsonTempFile);
    if (result.exitCode != 0) {
      return result.exitCode;
    } else {
      // intellij.py writes the list of modified files to stdout, so parse stdout and add the
      // resulting file paths to the modifiedFiles list.
      Iterable<String> paths = Splitter.on('\n').trimResults().omitEmptyStrings().split(
          result.stdOut);
      Iterables.addAll(modifiedFiles, paths);
    }

    // Write out the project.properties files.
    List<String> modifiedPropertiesFiles = generateProjectDotPropertiesFiles(modules);
    modifiedFiles.addAll(modifiedPropertiesFiles);

    // Write out the .idea/compiler.xml file (the .idea/ directory is guaranteed to exist).
    CompilerXml compilerXml = new CompilerXml(modules);
    final String pathToCompilerXml = ".idea/compiler.xml";
    File compilerXmlFile = projectFilesystem.getFileForRelativePath(pathToCompilerXml);
    if (compilerXml.write(compilerXmlFile)) {
      modifiedFiles.add(pathToCompilerXml);
    }

    // If the user specified a post-processing script, then run it.
    if (pathToPostProcessScript.isPresent()) {
      String pathToScript = pathToPostProcessScript.get();
      Process process = Runtime.getRuntime().exec(new String[] {pathToScript});
      processExecutor.execute(process);
    }

    // If any files have been modified by `buck project`, then list them for the user.
    if (!modifiedFiles.isEmpty()) {
      SortedSet<String> modifiedFilesInSortedForder = Sets.newTreeSet(modifiedFiles);
      stdOut.printf("MODIFIED FILES:\n%s\n", Joiner.on('\n').join(modifiedFilesInSortedForder));
    }
    // Blit stderr from intellij.py to parent stderr.
    stdErr.print(result.stdErr);

    return 0;
  }

  private List<String> generateProjectDotPropertiesFiles(List<Module> modules) throws IOException {
    if (GENERATE_PROPERTIES_FILES) {
      // Create a map of module names to modules.
      Map<String, Module> nameToModule = buildNameToModuleMap(modules);
      List<String> modifiedFiles = Lists.newArrayList();

      for (Module module : modules) {
        if (!module.isAndroidModule()) {
          continue;
        }

        File propertiesFile = writeProjectDotPropertiesFile(module, nameToModule);
        if (propertiesFile != null) {
          modifiedFiles.add(propertiesFile.getPath());
        }
      }

      return modifiedFiles;
    } else {
      return ImmutableList.of();
    }
  }

  @VisibleForTesting
  Map<String, Module> buildNameToModuleMap(List<Module> modules) {
    Map<String, Module> nameToModule = Maps.newHashMap();
    for (Module module : modules) {
      nameToModule.put(module.name, module);
    }
    return nameToModule;
  }

   /**
   * @param module must be an android module
   * @param nameToModuleIndex
   * @returns the File that was written, or {@code null} if no file was written.
   * @throws IOException
   */
  @VisibleForTesting
  @Nullable
  File writeProjectDotPropertiesFile(Module module, Map<String, Module> nameToModuleIndex)
      throws IOException {
    SortedSet<String> references = Sets.newTreeSet();
    for (DependentModule dependency : module.dependencies) {
      if (!dependency.isModule()) {
        continue;
      }

      Module dep = nameToModuleIndex.get(dependency.getModuleName());
      if (dep == null) {
        throw new HumanReadableException("You must define a project_config() in %s " +
            "containing %s. The project_config() in %s transitively depends on it.",
            module.target.getBasePathWithSlash() + BuckConstant.BUILD_RULES_FILE_NAME,
            dependency.getTargetName(),
            module.target.getFullyQualifiedName());
      }
      if (!dep.isAndroidModule()) {
        continue;
      }

      Path pathToImlFile = Paths.get(module.pathToImlFile);
      Path depPathToImlFile = Paths.get(dep.pathToImlFile);

      String relativePath = pathToImlFile.getParent().relativize(depPathToImlFile.getParent()).toString();

      // This is probably a self-reference. Ignore it.
      if (relativePath.isEmpty()) {
        continue;
      }

      references.add(relativePath);
    }

    StringBuilder builder = new StringBuilder();
    builder.append("# This file is automatically generated by Buck.\n");
    builder.append("# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n");

    // These are default values that IntelliJ or some other tool may overwrite.
    builder.append(
        String.format("target=%s\n", AndroidPlatformTarget.DEFAULT_ANDROID_PLATFORM_TARGET));
    builder.append("proguard.config=proguard.cfg\n");

    boolean isAndroidLibrary = module.isAndroidLibrary();
    if (isAndroidLibrary) {
      // Android does not seem to include this line for non-Android libraries.
      builder.append("android.library=" + isAndroidLibrary + "\n");
    }

    int index = 1;
    for (String path : references) {
      builder.append(String.format("android.library.reference.%d=%s\n", index, path));
      ++index;
    }

    final Charset charset = Charsets.US_ASCII;
    File outputFile = new File(createPathToProjectDotPropertiesFileFor(module));
    String properties = builder.toString();
    if (outputFile.exists() && Files.toString(outputFile, charset).equals(properties)) {
      return null;
    } else {
      Files.write(properties, outputFile, charset);
      return outputFile;
    }
  }

  @VisibleForTesting
  static String createPathToProjectDotPropertiesFileFor(Module module) {
    return module.getModuleDirectoryPathWithSlash() + "project.properties";
  }

  @VisibleForTesting
  PartialGraph getPartialGraph() {
    return partialGraph;
  }

  /**
   * This is used exclusively for testing and will only be populated after the modules are created.
   */
  @VisibleForTesting
  ImmutableSet<PrebuiltJarRule> getLibraryJars() {
    return ImmutableSet.copyOf(libraryJars);
  }

  @VisibleForTesting
  List<Module> createModulesForProjectConfigs() throws IOException {
    DependencyGraph dependencyGraph = partialGraph.getDependencyGraph();
    List<Module> modules = Lists.newArrayList();

    // Convert the project_config() targets into modules and find the union of all jars passed to
    // no_dx.
    ImmutableSet.Builder<String> noDxJarsBuilder = ImmutableSet.builder();
    for (BuildTarget target : partialGraph.getTargets()) {
      BuildRule buildRule = dependencyGraph.findBuildRuleByTarget(target);
      ProjectConfigRule projectConfigRule = (ProjectConfigRule)buildRule;

      BuildRule srcRule = projectConfigRule.getSrcRule();
      if (srcRule instanceof AndroidBinaryRule) {
        AndroidBinaryRule androidBinary = (AndroidBinaryRule)srcRule;
        AndroidDexTransitiveDependencies binaryDexTransitiveDependencies =
            androidBinary.findDexTransitiveDependencies(dependencyGraph);
        noDxJarsBuilder.addAll(binaryDexTransitiveDependencies.noDxClasspathEntries);
      }

      Module module = createModuleForProjectConfig(projectConfigRule);
      modules.add(module);
    }
    ImmutableSet<String> noDxJars = noDxJarsBuilder.build();

    // Update module dependencies to apply scope="PROVIDED", where appropriate.
    markNoDxJarsAsProvided(modules, noDxJars, dependencyGraph);

    return modules;
  }

  private Module createModuleForProjectConfig(ProjectConfigRule projectConfig) throws IOException {
    BuildRule projectRule = projectConfig.getProjectRule();
    Buildable buildable = projectRule.getBuildable();
    Preconditions.checkState(projectRule instanceof JavaLibraryRule
        || projectRule instanceof AndroidLibraryRule
        || projectRule instanceof AndroidResourceRule
        || projectRule instanceof AndroidBinaryRule
        || buildable instanceof NdkLibrary,
        "project_config() does not know how to process a src_target of type %s.",
        projectRule.getType().getName());

    LinkedHashSet<DependentModule> dependencies = Sets.newLinkedHashSet();
    final BuildTarget target = projectConfig.getBuildTarget();
    Module module = new Module(projectRule, target);
    module.name = getIntellijNameForRule(projectRule);
    module.isIntelliJPlugin = projectConfig.getIsIntelliJPlugin();

    String relativePath = projectConfig.getBuildTarget().getBasePathWithSlash();
    module.pathToImlFile = String.format("%s%s.iml", relativePath, module.name);

    // List the module source as the first dependency.
    boolean includeSourceFolder = true;

    // Do the tests before the sources so they appear earlier in the classpath. When tests are run,
    // their classpath entries may be deliberately shadowing production classpath entries.

    // tests folder
    boolean hasSourceFoldersForTestRule = addSourceFolders(module,
        projectConfig.getTestRule(),
        projectConfig.getTestsSourceRoots(),
        true /* isTestSource */);

    // test dependencies
    BuildRule testRule = projectConfig.getTestRule();
    if (testRule != null) {
      walkRuleAndAdd(testRule, true /* isForTests */, dependencies, projectConfig.getSrcRule());
    }

    // src folder
    boolean hasSourceFoldersForSrcRule = addSourceFolders(module,
        projectConfig.getSrcRule(),
        projectConfig.getSourceRoots(),
        false /* isTestSource */);

    // At least one of src or tests should contribute a source folder unless this is an
    // non-library Android project with no source roots specified.
    if (!hasSourceFoldersForTestRule && !hasSourceFoldersForSrcRule) {
      includeSourceFolder = false;
    }

    // IntelliJ expects all Android projects to have a gen/ folder, even if there is no src/
    // directory specified.
    boolean isAndroidRule = projectRule.getProperties().is(ANDROID);
    if (isAndroidRule) {
      boolean hasSourceFolders = !module.sourceFolders.isEmpty();
      module.sourceFolders.add(SourceFolder.GEN);
      if (!hasSourceFolders) {
        includeSourceFolder = true;
      }
    }

    // src dependencies
    // Note that isForTests is false even if projectRule is the project_config's test_target.
    walkRuleAndAdd(projectRule, false /* isForTests */, dependencies, projectConfig.getSrcRule());

    String basePathWithSlash = projectConfig.getBuildTarget().getBasePathWithSlash();

    // Specify another path for intellij to generate gen/ for each android module,
    // so that it will not disturb our glob() rules.
    // To specify the location of gen, Intellij requires the relative path from
    // the base path of current build target.
    module.moduleGenPath = generateRelativeGenPath(basePathWithSlash).toString();

    DependentModule jdkDependency;
    if (isAndroidRule) {
      // android details
      if (projectRule.getBuildable() instanceof NdkLibrary) {
        NdkLibrary ndkLibrary = (NdkLibrary) projectRule.getBuildable();
        module.isAndroidLibraryProject = true;
        module.keystorePath = null;
        module.nativeLibs = Paths.get(relativePath).relativize(Paths.get(ndkLibrary.getLibraryPath())).toString();
      } else if (projectRule instanceof AndroidResourceRule) {
        AndroidResourceRule androidResourceRule = (AndroidResourceRule)projectRule;
        module.resFolder = createRelativePath(androidResourceRule.getRes(), target);
        module.isAndroidLibraryProject = true;
        module.keystorePath = null;
      } else if (projectRule instanceof AndroidBinaryRule) {
        AndroidBinaryRule androidBinaryRule = (AndroidBinaryRule)projectRule;
        module.resFolder = null;
        module.isAndroidLibraryProject = false;
        KeystoreProperties keystoreProperties = KeystoreProperties.createFromPropertiesFile(
            androidBinaryRule.getKeystore().getPathToStore(),
            androidBinaryRule.getKeystore().getPathToPropertiesFile(),
            projectFilesystem);

        // getKeystore() returns a path relative to the project root, but an IntelliJ module
        // expects the path to the keystore to be relative to the module root.
        module.keystorePath = Paths.get(relativePath).relativize(Paths.get(keystoreProperties.getKeystore())).toString();
      } else {
        module.isAndroidLibraryProject = true;
        module.keystorePath = null;
      }

      module.hasAndroidFacet = true;
      module.proguardConfigPath = null;

      // If there is a default AndroidManifest.xml specified in .buckconfig, use it if
      // AndroidManifest.xml is not present in the root of the [Android] IntelliJ module.
      if (pathToDefaultAndroidManifest.isPresent()) {
        String androidManifest = basePathWithSlash + "AndroidManifest.xml";
        if (!projectFilesystem.exists(androidManifest)) {
          String manifestPath = this.pathToDefaultAndroidManifest.get();
          String rootPrefix = "//";
          Preconditions.checkState(manifestPath.startsWith(rootPrefix),
              "Currently, we expect this option to start with '%s', " +
              "indicating that it is relative to the root of the repository.",
              rootPrefix);
          manifestPath = manifestPath.substring(rootPrefix.length());
          String relativePathToManifest = Paths.get(basePathWithSlash).relativize(Paths.get(manifestPath)).toString();
          // IntelliJ requires that the path start with a slash to indicate that it is relative to
          // the module.
          module.androidManifest = "/" + relativePathToManifest;
        }
      }

      // List this last so that classes from modules can shadow classes in the JDK.
      jdkDependency = DependentModule.newInheritedJdk();
    } else {
      module.hasAndroidFacet = false;

      if (module.isIntelliJPlugin()) {
        jdkDependency = DependentModule.newIntelliJPluginJdk();
      } else {
        jdkDependency = DependentModule.newStandardJdk();
      }
    }

    // Assign the dependencies.
    module.dependencies = createDependenciesInOrder(
        includeSourceFolder, dependencies, jdkDependency);

    // Annotation processing generates sources for IntelliJ to consume, but does so outside
    // the module directory to avoid messing up globbing.
    if (projectRule instanceof JavaLibraryRule) {
      JavaLibraryRule javaLibraryRule = (JavaLibraryRule)projectRule;
      AnnotationProcessingData processingData = javaLibraryRule.getAnnotationProcessingData();

      String annotationGenSrc = processingData.getGeneratedSourceFolderName();
      if (annotationGenSrc != null) {
        module.annotationGenPath =
            "/" + Paths.get(basePathWithSlash).relativize(Paths.get(annotationGenSrc)).toString();
        module.annotationGenIsForTest = !hasSourceFoldersForSrcRule;
      }
    }

    return module;
  }

  private List<DependentModule> createDependenciesInOrder(
      boolean includeSourceFolder,
      LinkedHashSet<DependentModule> dependencies,
      DependentModule jdkDependency) {
    List<DependentModule> dependenciesInOrder = Lists.newArrayList();

    // If the source folder module is present, add it to the front of the list.
    if (includeSourceFolder) {
      dependenciesInOrder.add(DependentModule.newSourceFolder());
    }

    // List the libraries before the non-libraries.
    List<DependentModule> nonLibraries = Lists.newArrayList();
    for (DependentModule dep : dependencies) {
      if (dep.isLibrary()) {
        dependenciesInOrder.add(dep);
      } else {
        nonLibraries.add(dep);
      }
    }
    dependenciesInOrder.addAll(nonLibraries);

    // Add the JDK last.
    dependenciesInOrder.add(jdkDependency);
    return dependenciesInOrder;
  }

  /**
   * Paths.computeRelativePath(basePathWithSlash, "") generates the relative path
   * from base path of current build target to the root of the project.
   *
   * Paths.computeRelativePath("", basePathWithSlash) generates the relative path
   * from the root of the project to base path of current build target.
   *
   * For example, for the build target in $PROJECT_DIR$/android_res/com/facebook/gifts/,
   * Intellij will generate $PROJECT_DIR$/buck-out/android/android_res/com/facebook/gifts/gen
   *
   * @return the relative path of gen from the base path of current module.
   */
  static Path generateRelativeGenPath(String basePathOfModuleWithSlash) {
    return Paths.get(
        "/",
        Paths.get(basePathOfModuleWithSlash).relativize(Paths.get("")).toString(),
        ANDROID_GEN_DIR,
        Paths.get("").relativize(Paths.get(basePathOfModuleWithSlash)).toString(),
        "gen");
  }

  private boolean addSourceFolders(Module module,
      @Nullable BuildRule buildRule,
      @Nullable ImmutableList<SourceRoot> sourceRoots,
      boolean isTestSource) {
    if (buildRule == null || sourceRoots == null) {
      return false;
    }

    if (buildRule instanceof AndroidBinaryRule && sourceRoots.isEmpty()) {
      return false;
    }

    if (sourceRoots.isEmpty()) {
      // When there is a src_target, but no src_roots were specified, then the current directory is
      // treated as the SourceRoot. This is the common case when a project contains one folder of
      // Java source code with a build file for each Java package. For example, if the project's
      // only source folder were named "java/" and a build file in java/com/example/base/ contained
      // the an extremely simple set of build rules:
      //
      // java_library(
      //   name = 'base',
      //   srcs = glob(['*.java']),
      // }
      //
      // project_config(
      //   src_target = ':base',
      // )
      //
      // then the corresponding .iml file (in the same directory) should contain:
      //
      // <content url="file://$MODULE_DIR$">
      //   <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" packagePrefix="com.example.base" />
      //   <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
      //
      //   <!-- It will have an <excludeFolder> for every "subpackage" of com.example.base. -->
      //   <excludeFolder url="file://$MODULE_DIR$/util" />
      // </content>
      //
      // Note to prevent the <excludeFolder> elements from being included, the project_config()
      // rule should be:
      //
      // project_config(
      //   src_target = ':base',
      //   src_root_includes_subdirectories = True,
      // )
      //
      // Because developers who organize their code this way will have many build files, the default
      // values of project_config() assume this approach to help minimize the tedium in writing all
      // of those project_config() rules.
      String url = "file://$MODULE_DIR$";
      String packagePrefix = javaPackageFinder.findJavaPackageForPath(module.pathToImlFile);
      SourceFolder sourceFolder = new SourceFolder(url, isTestSource, packagePrefix);
      module.sourceFolders.add(sourceFolder);
    } else {
      for (SourceRoot sourceRoot : sourceRoots) {
        SourceFolder sourceFolder = new SourceFolder(
            String.format("file://$MODULE_DIR$/%s", sourceRoot.getName()), isTestSource);
        module.sourceFolders.add(sourceFolder);
      }
    }

    // Include <excludeFolder> elements, as appropriate.
    for (String relativePath : this.buildFileTree.getChildPaths(buildRule.getBuildTarget())) {
      String excludeFolderUrl = "file://$MODULE_DIR$/" + relativePath;
      SourceFolder excludeFolder = new SourceFolder(excludeFolderUrl, /* isTestSource */ false);
      module.excludeFolders.add(excludeFolder);
    }

    // If in the root of the project, specify ignored paths.
    if ("".equals(buildRule.getBuildTarget().getBasePathWithSlash())) {
      for (String path : projectFilesystem.getIgnorePaths()) {
        module.excludeFolders.add(new SourceFolder(String.format("file://$MODULE_DIR$/%s", path),
            false));
      }
    }

    return true;
  }

  /**
   * Modifies the {@code scope} of a library dependency to {@code "PROVIDED"}, where appropriate.
   * <p>
   * If an {@code android_binary()} rule uses the {@code no_dx} argument, then the jars in the
   * libraries that should not be dex'ed must be included with {@code scope="PROVIDED"} in
   * IntelliJ.
   * <p>
   * The problem is that if a library is included by two android_binary rules that each need it in a
   * different way (i.e., for one it should be {@code scope="COMPILE"} and another it should be
   * {@code scope="PROVIDED"}), then it must be tagged as {@code scope="PROVIDED"} in all
   * dependent modules and then added as {@code scope="COMPILE"} in the .iml file that corresponds
   * to the android_binary that <em>does not</em> list the library in its {@code no_dx} list.
   */
  @VisibleForTesting
  static void markNoDxJarsAsProvided(
      List<Module> modules,
      Set<String> noDxJars,
        DependencyGraph dependencyGraph) {
  Map<String, String> intelliJLibraryNameToJarPath = Maps.newHashMap();
    for (String jarPath : noDxJars) {
      String libraryName = getIntellijNameForBinaryJar(jarPath);
      intelliJLibraryNameToJarPath.put(libraryName, jarPath);
    }

    for (Module module : modules) {
      // For an android_binary() rule, create a set of paths to JAR files (or directories) that
      // must be dex'ed. If a JAR file that is in the no_dx list for some android_binary rule, but
      // is in this set for this android_binary rule, then it should be scope="COMPILE" rather than
      // scope="PROVIDED".
      Set<String> classpathEntriesToDex;
      if (module.srcRule instanceof AndroidBinaryRule) {
        AndroidBinaryRule androidBinaryRule = (AndroidBinaryRule)module.srcRule;
        AndroidDexTransitiveDependencies dexTransitiveDependencies =
            androidBinaryRule.findDexTransitiveDependencies(dependencyGraph);
        classpathEntriesToDex = Sets.newHashSet(Sets.intersection(noDxJars,
            dexTransitiveDependencies.classpathEntriesToDex));
      } else {
        classpathEntriesToDex = ImmutableSet.of();
      }

      // Inspect all of the library dependencies. If the corresponding JAR file is in the set of
      // noDxJars, then either change its scope to "COMPILE" or "PROVIDED", as appropriate.
      for (DependentModule dependentModule : module.dependencies) {
        if (!dependentModule.isLibrary()) {
          continue;
        }

        // This is the IntelliJ name for the library that corresponds to the PrebuiltJarRule.
        String libraryName = dependentModule.getLibraryName();

        String jarPath = intelliJLibraryNameToJarPath.get(libraryName);
        if (jarPath != null) {
          if (classpathEntriesToDex.contains(jarPath)) {
            dependentModule.scope = null;
            classpathEntriesToDex.remove(jarPath);
          } else {
            dependentModule.scope = "PROVIDED";
          }
        }
      }

      // Make sure that every classpath entry that is also in noDxJars is added with scope="COMPILE"
      // if it has not already been added to the module.
      for (String entry : classpathEntriesToDex) {
        String libraryName = getIntellijNameForBinaryJar(entry);
        DependentModule dependency = DependentModule.newLibrary(null, libraryName);
        module.dependencies.add(dependency);
      }
    }
  }

  /**
   * Walks the dependencies of a build rule and adds the appropriate DependentModules to the
   * specified dependencies collection. All library dependencies will be added before any module
   * dependencies. See {@link ProjectTest#testThatJarsAreListedBeforeModules()} for details on why
   * this behavior is important.
   */
  private void walkRuleAndAdd(
      final BuildRule rule,
      final boolean isForTests,
      final LinkedHashSet<DependentModule> dependencies,
      @Nullable final BuildRule srcTarget) {

    final String basePathForRule = rule.getBuildTarget().getBasePath();
    new AbstractDependencyVisitor(rule, true /* excludeRoot */) {

      private final LinkedHashSet<DependentModule> librariesToAdd = Sets.newLinkedHashSet();
      private final LinkedHashSet<DependentModule> modulesToAdd = Sets.newLinkedHashSet();

      @Override
      public ImmutableSet<BuildRule> visit(BuildRule dep) {
        ImmutableSet<BuildRule> depsToVisit;
        if (rule.getProperties().is(PACKAGING) ||
            dep instanceof AndroidResourceRule ||
            dep == rule) {
          depsToVisit = dep.getDeps();
        } else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) {
          depsToVisit = ((ExportDependencies)dep).getExportedDeps();
        } else {
          depsToVisit = ImmutableSet.of();
        }

        // Special Case: If we are traversing the test_target and we encounter a library rule in the
        // same package that is not the src_target, then we should traverse the deps. Consider the
        // following build file:
        //
        // android_library(
        //   name = 'lib',
        //   srcs = glob(['*.java'], excludes = ['*Test.java']),
        //   deps = [
        //     # LOTS OF DEPS
        //   ],
        // )
        //
        // java_test(
        //   name = 'test',
        //   srcs = glob(['*Test.java']),
        //   deps = [
        //     ':lib',
        //     # MOAR DEPS
        //   ],
        // )
        //
        // project_config(
        //   test_target = ':test',
        // )
        //
        // Note that the only source folder for this IntelliJ module is the current directory. Thus,
        // the current directory should be treated as a source folder with test sources, but it
        // should contain the union of :lib and :test's deps as dependent modules.
        if (isForTests
            && depsToVisit.isEmpty()
            && dep.getBuildTarget().getBasePath().equals(basePathForRule)
            && !dep.equals(srcTarget)) {
          depsToVisit = dep.getDeps();
        }

        DependentModule dependentModule;
        if (dep instanceof PrebuiltJarRule) {
          libraryJars.add((PrebuiltJarRule) dep);
          String libraryName = getIntellijNameForRule(dep);
          dependentModule = DependentModule.newLibrary(dep.getBuildTarget(), libraryName);
        } else if (dep instanceof NdkLibrary) {
          String moduleName = getIntellijNameForRule(dep);
          dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName);
        } else if (dep.getFullyQualifiedName().startsWith(ANDROID_GEN_BUILD_TARGET_PREFIX)) {
          return depsToVisit;
        } else if (dep instanceof JavaLibraryRule || dep instanceof AndroidResourceRule) {
          String moduleName = getIntellijNameForRule(dep);
          dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName);
        } else {
          return depsToVisit;
        }

        if (isForTests) {
          dependentModule.scope = "TEST";
        } else {
          // If the dependentModule has already been added in the "TEST" scope, then it should be
          // removed and then re-added using the current (compile) scope.
          String currentScope = dependentModule.scope;
          dependentModule.scope = "TEST";
          if (dependencies.contains(dependentModule)) {
            dependencies.remove(dependentModule);
          }
          dependentModule.scope = currentScope;
        }

        // Slate the module for addition to the dependencies collection. Modules are added to
        // dependencies collection once the traversal is complete in the onComplete() method.
        if (dependentModule.isLibrary()) {
          librariesToAdd.add(dependentModule);
        } else {
          modulesToAdd.add(dependentModule);
        }

        return depsToVisit;
      }

      @Override
      protected void onComplete() {
        dependencies.addAll(librariesToAdd);
        dependencies.addAll(modulesToAdd);
      }
    }.start();
  }

  /**
   * Maps a BuildRule to the name of the equivalent IntelliJ library or module.
   */
  private String getIntellijNameForRule(BuildRule rule) {
    return Project.getIntellijNameForRule(rule, basePathToAliasMap);
  }

  /**
   * @param rule whose corresponding IntelliJ module name will be returned
   * @param basePathToAliasMap may be null if rule is a {@link PrebuiltJarRule}
   */
  private static String getIntellijNameForRule(BuildRule rule,
      @Nullable Map<String, String> basePathToAliasMap) {
    // Get basis for the library/module name.
    String name;
    if (rule instanceof PrebuiltJarRule) {
      PrebuiltJarRule prebuiltJarRule = (PrebuiltJarRule)rule;
      String binaryJar = prebuiltJarRule.getBinaryJar();
      return getIntellijNameForBinaryJar(binaryJar);
    } else {
      String basePath = rule.getBuildTarget().getBasePath();
      if (basePathToAliasMap.containsKey(basePath)) {
        name = basePathToAliasMap.get(basePath);
      } else {
        name = rule.getBuildTarget().getBasePath();
        name = name.replace('/', '_');
        // Must add a prefix to ensure that name is non-empty.
        name = "module_" + name;
      }
      // Normalize name.
      return normalizeIntelliJName(name);
    }
  }

  private static String getIntellijNameForBinaryJar(String binaryJar) {
    String name = binaryJar.replace('/', '_');
    return normalizeIntelliJName(name);
  }

  private static String normalizeIntelliJName(String name) {
    return name.replace('.', '_').replace('-', '_');
  }

  /**
   * @param pathRelativeToProjectRoot if {@code null}, then this method returns {@code null}
   * @param target
   */
  private static String createRelativePath(@Nullable String pathRelativeToProjectRoot,
      BuildTarget target) {
    if (pathRelativeToProjectRoot == null) {
      return null;
    }
    String directoryPath = target.getBasePath();
    Preconditions.checkArgument(pathRelativeToProjectRoot.startsWith(directoryPath));
    return pathRelativeToProjectRoot.substring(directoryPath.length());
  }

  private void writeJsonConfig(File jsonTempFile, List<Module> modules) throws IOException {
    List<SerializablePrebuiltJarRule> libraries = Lists.newArrayListWithCapacity(
        libraryJars.size());
    for (PrebuiltJarRule libraryJar : libraryJars) {
      libraries.add(new SerializablePrebuiltJarRule(libraryJar));
    }

    Map<String, Object> config = ImmutableMap.<String, Object>of(
        "modules", modules,
        "libraries", libraries);

    // Write out the JSON config to be consumed by the Python.
    Writer writer = new FileWriter(jsonTempFile);
    JsonFactory jsonFactory = new JsonFactory();
    ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
    if (executionContext.getVerbosity().shouldPrintOutput()) {
      ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
      objectWriter.writeValue(writer, config);
    } else {
      objectMapper.writeValue(writer, config);
    }
  }

  private ExitCodeAndOutput processJsonConfig(File jsonTempFile) throws IOException {
    final ImmutableList<String> args = ImmutableList.of(
        pythonInterpreter, PATH_TO_INTELLIJ_PY, jsonTempFile.getAbsolutePath());

    ShellStep command = new ShellStep() {

      @Override
      public String getShortName() {
        return "python";
      }

      @Override
      protected ImmutableList<String> getShellCommandInternal(
          ExecutionContext context) {
        return args;
      }
    };

    Console console = executionContext.getConsole();
    Console childConsole = new Console(
        Verbosity.SILENT,
        console.getStdOut(),
        console.getStdErr(),
        Ansi.withoutTty());
    ExecutionContext childContext = ExecutionContext.builder()
        .setExecutionContext(executionContext)
        .setConsole(childConsole)
        .build();
    int exitCode = command.execute(childContext);
    return new ExitCodeAndOutput(exitCode, command.getStdout(), command.getStderr());
  }

  private static class ExitCodeAndOutput {
    private final int exitCode;
    private final String stdOut;
    private final String stdErr;
    ExitCodeAndOutput(int exitCode, String stdOut, String stdErr) {
      this.exitCode = exitCode;
      this.stdOut = Preconditions.checkNotNull(stdOut);
      this.stdErr = Preconditions.checkNotNull(stdErr);
    }
  }

  @JsonInclude(Include.NON_NULL)
  @VisibleForTesting
  static class SourceFolder {
    @JsonProperty
    private final String url;

    @JsonProperty
    private final boolean isTestSource;

    @JsonProperty
    @Nullable
    private final String packagePrefix;

    static final SourceFolder SRC = new SourceFolder("file://$MODULE_DIR$/src", false);
    static final SourceFolder TESTS = new SourceFolder("file://$MODULE_DIR$/tests", true);
    static final SourceFolder GEN = new SourceFolder("file://$MODULE_DIR$/gen", false);

    SourceFolder(String url, boolean isTestSource) {
      this(url, isTestSource, null /* packagePrefix */);
    }

    SourceFolder(String url, boolean isTestSource, @Nullable String packagePrefix) {
      this.url = url;
      this.isTestSource = isTestSource;
      this.packagePrefix = packagePrefix;
    }

    String getUrl() {
      return url;
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof SourceFolder)) {
        return false;
      }
      SourceFolder that = (SourceFolder)obj;
      return Objects.equal(this.url, that.url)
          && Objects.equal(this.isTestSource, that.isTestSource)
          && Objects.equal(this.packagePrefix, that.packagePrefix);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(url, isTestSource, packagePrefix);
    }

    @Override
    public String toString() {
      return Objects.toStringHelper(SourceFolder.class)
          .add("url", url)
          .add("isTestSource", isTestSource)
          .add("packagePrefix", packagePrefix)
          .toString();
    }
  }

  @JsonInclude(Include.NON_NULL)
  @VisibleForTesting
  static class SerializablePrebuiltJarRule {
    @JsonProperty private final String name;
    @JsonProperty private final String binaryJar;
    @JsonProperty private final String sourceJar;
    @JsonProperty private final String javadocUrl;

    private SerializablePrebuiltJarRule(PrebuiltJarRule rule) {
      this.name = getIntellijNameForRule(rule, null /* basePathToAliasMap */);
      this.binaryJar = rule.getBinaryJar();
      this.sourceJar = rule.getSourceJar().orNull();
      this.javadocUrl = rule.getJavadocUrl().orNull();
    }

    @Override
    public String toString() {
      return Objects.toStringHelper(SerializablePrebuiltJarRule.class)
          .add("name", name)
          .add("binaryJar", binaryJar)
          .add("sourceJar", sourceJar)
          .add("javadocUrl", javadocUrl)
          .toString();
    }
  }

}
