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

import com.facebook.buck.apple.AppleBuildRules;
import com.facebook.buck.apple.AppleTestDescription;
import com.facebook.buck.apple.ProjectGenerator;
import com.facebook.buck.apple.WorkspaceAndProjectGenerator;
import com.facebook.buck.apple.XcodeWorkspaceConfigDescription;
import com.facebook.buck.java.JavaLibraryDescription;
import com.facebook.buck.java.intellij.Project;
import com.facebook.buck.json.BuildFileParseException;
import com.facebook.buck.log.Logger;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetException;
import com.facebook.buck.model.FilesystemBackedBuildFileTree;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.parser.BuildTargetSpec;
import com.facebook.buck.parser.ParserConfig;
import com.facebook.buck.parser.TargetNodePredicateSpec;
import com.facebook.buck.parser.TargetNodeSpec;
import com.facebook.buck.python.PythonBuckConfig;
import com.facebook.buck.rules.ActionGraph;
import com.facebook.buck.rules.AssociatedTargetNodePredicate;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.ProjectConfig;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetGraphAndTargets;
import com.facebook.buck.rules.TargetGraphToActionGraph;
import com.facebook.buck.rules.TargetGraphTransformer;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.ProcessManager;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.io.Files;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class ProjectCommand extends AbstractCommandRunner<ProjectCommandOptions> {

  private static final Logger LOG = Logger.get(ProjectCommand.class);

  /**
   * Include java library targets (and android library targets) that use annotation
   * processing.  The sources generated by these annotation processors is needed by
   * IntelliJ.
   */
  private static final Predicate<TargetNode<?>> ANNOTATION_PREDICATE =
      new Predicate<TargetNode<?>>() {
        @Override
        public boolean apply(TargetNode<?> input) {
          if (input.getType() != JavaLibraryDescription.TYPE) {
            return false;
          }
          JavaLibraryDescription.Arg arg = ((JavaLibraryDescription.Arg) input.getConstructorArg());
          return !arg.annotationProcessors.get().isEmpty();
        }
      };

  private static final String XCODE_PROCESS_NAME = "Xcode";

  private final TargetGraphTransformer<ActionGraph> targetGraphTransformer;

  public ProjectCommand(CommandRunnerParams params) {
    super(params);

    this.targetGraphTransformer = new TargetGraphToActionGraph(
        params.getBuckEventBus(),
        new BuildTargetNodeToBuildRuleTransformer());
  }

  @Override
  ProjectCommandOptions createOptions(BuckConfig buckConfig) {
    return new ProjectCommandOptions(buckConfig);
  }

  @Override
  int runCommandWithOptionsInternal(ProjectCommandOptions options)
      throws IOException, InterruptedException {
    if (options.getIde() == ProjectCommandOptions.Ide.XCODE) {
      checkForAndKillXcodeIfRunning(options.getIdePrompt());
    }

    ImmutableSet<BuildTarget> passedInTargetsSet =
        getBuildTargets(options.getArgumentsFormattedAsBuildTargets());
    ProjectGraphParser projectGraphParser = ProjectGraphParsers.createProjectGraphParser(
        getParser(),
        new ParserConfig(options.getBuckConfig()),
        getBuckEventBus(),
        console,
        environment,
        options.getEnableProfiling());

    TargetGraph projectGraph = projectGraphParser.buildTargetGraphForTargetNodeSpecs(
        getTargetNodeSpecsForIde(
            options.getIde(),
            passedInTargetsSet,
            getProjectFilesystem().getIgnorePaths()));

    ProjectPredicates projectPredicates = ProjectPredicates.forIde(options.getIde());

    ImmutableSet<BuildTarget> graphRoots;
    if (!passedInTargetsSet.isEmpty()) {
      graphRoots = passedInTargetsSet;
    } else {
      graphRoots = getRootsFromPredicate(
          projectGraph,
          projectPredicates.getProjectRootsPredicate());
    }

    TargetGraphAndTargets targetGraphAndTargets = createTargetGraph(
          projectGraph,
          graphRoots,
          projectGraphParser,
          projectPredicates.getAssociatedProjectPredicate(),
          options.isWithTests(),
          options.getIde(),
          getProjectFilesystem().getIgnorePaths());

    if (options.getDryRun()) {
      for (TargetNode<?> targetNode : targetGraphAndTargets.getTargetGraph().getNodes()) {
        console.getStdOut().println(targetNode.toString());
      }

      return 0;
    }

    switch (options.getIde()) {
      case INTELLIJ:
        return runIntellijProjectGenerator(
            projectGraph,
            targetGraphAndTargets,
            passedInTargetsSet,
            options);
      case XCODE:
        return runXcodeProjectGenerator(
            targetGraphAndTargets,
            passedInTargetsSet,
            options);
      default:
        // unreachable
        throw new IllegalStateException("'ide' should always be of type 'INTELLIJ' or 'XCODE'");
    }
  }

  /**
   * Run intellij specific project generation actions.
   */
  int runIntellijProjectGenerator(
      TargetGraph projectGraph,
      TargetGraphAndTargets targetGraphAndTargets,
      ImmutableSet<BuildTarget> passedInTargetsSet,
      ProjectCommandOptions options)
      throws IOException, InterruptedException {
    // Create an ActionGraph that only contains targets that can be represented as IDE
    // configuration files.
    ActionGraph actionGraph = targetGraphTransformer.apply(targetGraphAndTargets.getTargetGraph());

    try (ExecutionContext executionContext = createExecutionContext()) {
      Project project = new Project(
          new SourcePathResolver(new BuildRuleResolver(actionGraph.getNodes())),
          FluentIterable
              .from(actionGraph.getNodes())
              .filter(ProjectConfig.class)
              .toSet(),
          actionGraph,
          options.getBasePathToAliasMap(),
          options.getJavaPackageFinder(),
          executionContext,
          new FilesystemBackedBuildFileTree(
              getProjectFilesystem(),
              new ParserConfig(options.getBuckConfig()).getBuildFileName()),
          getProjectFilesystem(),
          options.getPathToDefaultAndroidManifest(),
          options.getPathToPostProcessScript(),
          new PythonBuckConfig(options.getBuckConfig()).getPythonInterpreter(),
          getObjectMapper(),
          options.isAndroidAutoGenerateEnabled());

      File tempDir = Files.createTempDir();
      File tempFile = new File(tempDir, "project.json");
      int exitCode;
      try {
        exitCode = project.createIntellijProject(
            tempFile,
            executionContext.getProcessExecutor(),
            !passedInTargetsSet.isEmpty(),
            console.getStdOut(),
            console.getStdErr());
        if (exitCode != 0) {
          return exitCode;
        }

        List<String> additionalInitialTargets = ImmutableList.of();
        if (options.shouldProcessAnnotations()) {
          try {
            additionalInitialTargets = getAnnotationProcessingTargets(
                projectGraph,
                passedInTargetsSet);
          } catch (BuildTargetException | BuildFileParseException e) {
            throw new HumanReadableException(e);
          }
        }

        // Build initial targets.
        if (options.hasInitialTargets() || !additionalInitialTargets.isEmpty()) {
          BuildCommand buildCommand = new BuildCommand(getCommandRunnerParams());
          BuildCommandOptions buildOptions =
              options.createBuildCommandOptionsWithInitialTargets(additionalInitialTargets);


          exitCode = buildCommand.runCommandWithOptions(buildOptions);
          if (exitCode != 0) {
            return exitCode;
          }
        }
      } finally {
        // Either leave project.json around for debugging or delete it on exit.
        if (console.getVerbosity().shouldPrintOutput()) {
          getStdErr().printf("project.json was written to %s", tempFile.getAbsolutePath());
        } else {
          tempFile.delete();
          tempDir.delete();
        }
      }

      if (passedInTargetsSet.isEmpty()) {
        String greenStar = console.getAnsi().asHighlightedSuccessText(" * ");
        getStdErr().printf(
            console.getAnsi().asHighlightedSuccessText("=== Did you know ===") + "\n" +
            greenStar + "You can run `buck project <target>` to generate a minimal project " +
            "just for that target.\n" +
            greenStar + "This will make your IDE faster when working on large projects.\n" +
            greenStar + "See buck project --help for more info.\n" +
            console.getAnsi().asHighlightedSuccessText(
                "--=* Knowing is half the battle!") + "\n");
      }

      return 0;
    }
  }

  ImmutableList<String> getAnnotationProcessingTargets(
      TargetGraph projectGraph,
      ImmutableSet<BuildTarget> passedInTargetsSet)
      throws BuildTargetException, BuildFileParseException, IOException, InterruptedException {
    ImmutableSet<BuildTarget> buildTargets;
    if (!passedInTargetsSet.isEmpty()) {
      buildTargets = passedInTargetsSet;
    } else {
      buildTargets = getRootsFromPredicate(
          projectGraph,
          ANNOTATION_PREDICATE);
    }
    return FluentIterable
        .from(buildTargets)
        .transform(Functions.toStringFunction())
        .toList();
  }

  /**
   * Run xcode specific project generation actions.
   */
  int runXcodeProjectGenerator(
      TargetGraphAndTargets targetGraphAndTargets,
      ImmutableSet<BuildTarget> passedInTargetsSet,
      ProjectCommandOptions options)
      throws IOException, InterruptedException {
    ImmutableSet.Builder<ProjectGenerator.Option> optionsBuilder = ImmutableSet.builder();
    if (options.getReadOnly()) {
      optionsBuilder.add(ProjectGenerator.Option.GENERATE_READ_ONLY_FILES);
    }
    if (options.isWithTests()) {
      optionsBuilder.add(ProjectGenerator.Option.INCLUDE_TESTS);
    }

    boolean combinedProject = options.getCombinedProject();
    ImmutableSet<BuildTarget> targets;
    if (passedInTargetsSet.isEmpty()) {
      targets = FluentIterable
          .from(targetGraphAndTargets.getProjectRoots())
          .transform(HasBuildTarget.TO_TARGET)
          .toSet();
    } else {
      targets = passedInTargetsSet;
    }
    if (combinedProject) {
      optionsBuilder.addAll(ProjectGenerator.COMBINED_PROJECT_OPTIONS);
    } else {
      optionsBuilder.addAll(ProjectGenerator.SEPARATED_PROJECT_OPTIONS);
    }
    LOG.debug("Generating workspace for config targets %s", targets);
    Map<Path, ProjectGenerator> projectGenerators = new HashMap<>();
    ImmutableSet<TargetNode<?>> testTargetNodes = targetGraphAndTargets.getAssociatedTests();
    ImmutableSet<TargetNode<AppleTestDescription.Arg>> groupableTests =
      options.getCombineTestBundles()
          ? AppleBuildRules.filterGroupableTests(testTargetNodes)
          : ImmutableSet.<TargetNode<AppleTestDescription.Arg>>of();
    for (BuildTarget workspaceTarget : targets) {
      TargetNode<?> workspaceNode = Preconditions.checkNotNull(
          targetGraphAndTargets.getTargetGraph().get(workspaceTarget));
      if (workspaceNode.getType() != XcodeWorkspaceConfigDescription.TYPE) {
        throw new HumanReadableException(
            "%s must be a xcode_workspace_config",
            workspaceTarget);
      }
      WorkspaceAndProjectGenerator generator = new WorkspaceAndProjectGenerator(
          getProjectFilesystem(),
          targetGraphAndTargets.getTargetGraph(),
          castToXcodeWorkspaceTargetNode(workspaceNode),
          optionsBuilder.build(),
          combinedProject,
          new ParserConfig(options.getBuckConfig()).getBuildFileName());
      generator.setGroupableTests(groupableTests);
      generator.generateWorkspaceAndDependentProjects(projectGenerators);
    }

    return 0;
  }

  @SuppressWarnings(value = "unchecked")
  private static TargetNode<XcodeWorkspaceConfigDescription.Arg> castToXcodeWorkspaceTargetNode(
      TargetNode<?> targetNode) {
    Preconditions.checkArgument(targetNode.getType() == XcodeWorkspaceConfigDescription.TYPE);
    return (TargetNode<XcodeWorkspaceConfigDescription.Arg>) targetNode;
  }

  private void checkForAndKillXcodeIfRunning(boolean enablePrompt)
      throws InterruptedException, IOException {
    Optional<ProcessManager> processManager = getProcessManager();
    if (!processManager.isPresent()) {
      LOG.warn("Could not check if Xcode is running (no process manager)");
      return;
    }

    if (!processManager.get().isProcessRunning(XCODE_PROCESS_NAME)) {
      LOG.debug("Xcode is not running.");
      return;
    }

    if (enablePrompt && canPrompt()) {
      if (prompt(
              "Xcode is currently running. Buck will modify files Xcode currently has " +
              "open, which can cause it to become unstable.\n\n" +
              "Kill Xcode and continue?")) {
        processManager.get().killProcess(XCODE_PROCESS_NAME);
      } else {
        console.getStdOut().println(
            console.getAnsi().asWarningText(
                "Xcode is running. Generated projects might be lost or corrupted if Xcode " +
                "currently has them open."));
      }
      console.getStdOut().format(
          "To disable this prompt in the future, add the following to %s: \n\n" +
              "[project]\n" +
              "  ide_prompt = false\n\n",
          getProjectFilesystem()
              .getRootPath()
              .resolve(BuckConfig.DEFAULT_BUCK_CONFIG_OVERRIDE_FILE_NAME)
              .toAbsolutePath());
    } else {
      LOG.debug(
          "Xcode is running, but cannot prompt to kill it (enabled %s, can prompt %s)",
          enablePrompt, canPrompt());
    }
  }

  private boolean canPrompt() {
    return System.console() != null;
  }

  private boolean prompt(String prompt) throws IOException {
    Preconditions.checkState(canPrompt());

    LOG.debug("Displaying prompt %s..", prompt);
    console.getStdOut().print(console.getAnsi().asWarningText(prompt + " [Y/n] "));

    Optional<String> result;
    try (InputStreamReader stdinReader = new InputStreamReader(System.in, Charsets.UTF_8);
         BufferedReader bufferedStdinReader = new BufferedReader(stdinReader)) {
      result = Optional.fromNullable(bufferedStdinReader.readLine());
    }
    LOG.debug("Result of prompt: [%s]", result);
    return result.isPresent() &&
      (result.get().isEmpty() || result.get().toLowerCase(Locale.US).startsWith("y"));
  }

  @VisibleForTesting
  static ImmutableSet<BuildTarget> getRootsFromPredicate(
      TargetGraph projectGraph,
      Predicate<TargetNode<?>> rootsPredicate) {
    return FluentIterable
        .from(projectGraph.getNodes())
        .filter(rootsPredicate)
        .transform(HasBuildTarget.TO_TARGET)
        .toSet();
  }

  private static Iterable<? extends TargetNodeSpec> getTargetNodeSpecsForIde(
      ProjectCommandOptions.Ide ide,
      Collection<BuildTarget> passedInBuildTargets,
      ImmutableSet<Path> ignoreDirs
  ) {
    if (ide == ProjectCommandOptions.Ide.XCODE &&
        !passedInBuildTargets.isEmpty()) {
      return Iterables.transform(
          passedInBuildTargets,
          BuildTargetSpec.TO_BUILD_TARGET_SPEC);
    } else {
      return ImmutableList.of(
          new TargetNodePredicateSpec(
              Predicates.<TargetNode<?>>alwaysTrue(),
              ignoreDirs));
    }
  }

  private static TargetGraphAndTargets createTargetGraph(
      TargetGraph projectGraph,
      ImmutableSet<BuildTarget> graphRoots,
      ProjectGraphParser projectGraphParser,
      AssociatedTargetNodePredicate associatedProjectPredicate,
      boolean isWithTests,
      ProjectCommandOptions.Ide ide,
      ImmutableSet<Path> ignoreDirs
  )
    throws IOException, InterruptedException {

    TargetGraph resultProjectGraph;
    ImmutableSet<BuildTarget> explicitTestTargets;

    if (isWithTests) {
        explicitTestTargets = TargetGraphAndTargets.getExplicitTestTargets(
            graphRoots,
            projectGraph);
        resultProjectGraph =
            projectGraphParser.buildTargetGraphForTargetNodeSpecs(
                getTargetNodeSpecsForIde(
                    ide,
                    Sets.union(graphRoots, explicitTestTargets),
                    ignoreDirs));
    } else {
      resultProjectGraph = projectGraph;
      explicitTestTargets = ImmutableSet.of();
    }

    return TargetGraphAndTargets.create(
        graphRoots,
        resultProjectGraph,
        associatedProjectPredicate,
        isWithTests,
        explicitTestTargets);
  }

  @Override
  String getUsageIntro() {
    return "generates project configuration files for an IDE";
  }

}
