/*
 * Copyright 2014-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.apple;

import com.facebook.buck.apple.xcode.xcodeproj.PBXTarget;
import com.facebook.buck.graph.TopologicalSort;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.log.Logger;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.model.HasTests;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
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.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
import java.util.Set;

public class WorkspaceAndProjectGenerator {
  private static final Logger LOG = Logger.get(WorkspaceAndProjectGenerator.class);

  private final ProjectFilesystem projectFilesystem;
  private final TargetGraph projectGraph;
  private final TargetNode<XcodeWorkspaceConfigDescription.Arg> workspaceTargetNode;
  private final ImmutableSet<ProjectGenerator.Option> projectGeneratorOptions;
  private final ImmutableSet<TargetNode<AppleTestDescription.Arg>> extraTestBundleTargetNodes;
  private final boolean combinedProject;
  private ImmutableSet<TargetNode<AppleTestDescription.Arg>> groupableTests = ImmutableSet.of();

  private Optional<ProjectGenerator> combinedProjectGenerator;
  private Optional<ProjectGenerator> combinedTestsProjectGenerator = Optional.absent();
  private Optional<SchemeGenerator> schemeGenerator = Optional.absent();
  private String buildFileName;

  public WorkspaceAndProjectGenerator(
      ProjectFilesystem projectFilesystem,
      TargetGraph projectGraph,
      TargetNode<XcodeWorkspaceConfigDescription.Arg> workspaceTargetNode,
      Set<ProjectGenerator.Option> projectGeneratorOptions,
      boolean combinedProject,
      String buildFileName) {
    this.projectFilesystem = projectFilesystem;
    this.projectGraph = projectGraph;
    this.workspaceTargetNode = workspaceTargetNode;
    this.projectGeneratorOptions = ImmutableSet.copyOf(projectGeneratorOptions);
    this.combinedProject = combinedProject;
    this.buildFileName = buildFileName;
    this.combinedProjectGenerator = Optional.absent();
    extraTestBundleTargetNodes = getExtraTestTargetNodes(
        projectGraph, workspaceTargetNode.getConstructorArg().extraTests.get());
  }

  @VisibleForTesting
  Optional<ProjectGenerator> getCombinedProjectGenerator() {
    return combinedProjectGenerator;
  }

  @VisibleForTesting
  Optional<SchemeGenerator> getSchemeGenerator() {
    return schemeGenerator;
  }

  /**
   * Return the project generator to generate the combined test bundles.
   * This is only set when generating separated projects.
   */
  @VisibleForTesting
  Optional<ProjectGenerator> getCombinedTestsProjectGenerator() {
    return combinedTestsProjectGenerator;
  }

  /**
   * Set the tests that can be grouped. These tests will always be generated as static libraries,
   * and linked into synthetic test targets.
   *
   * While it may seem unnecessary to do this for tests which may not be able to share a bundle with
   * any other test, note that WorkspaceAndProjectGenerator only has a limited view of all the tests
   * that exists, but the generated projects are shared amongst all Workspaces.
   */
  public WorkspaceAndProjectGenerator setGroupableTests(
      Set<TargetNode<AppleTestDescription.Arg>> tests) {
    groupableTests = ImmutableSet.copyOf(tests);
    return this;
  }

  public Path generateWorkspaceAndDependentProjects(
        Map<Path, ProjectGenerator> projectGenerators)
      throws IOException {
    LOG.debug("Generating workspace for target %s", workspaceTargetNode);

    String workspaceName = XcodeWorkspaceConfigDescription.getWorkspaceNameFromArg(
        workspaceTargetNode.getConstructorArg());
    Path outputDirectory;
    if (combinedProject) {
      workspaceName += "-Combined";
      outputDirectory =
          BuildTargets.getGenPath(workspaceTargetNode.getBuildTarget(), "%s").getParent();
    } else {
      outputDirectory = workspaceTargetNode.getBuildTarget().getBasePath();
    }

    WorkspaceGenerator workspaceGenerator = new WorkspaceGenerator(
        projectFilesystem,
        workspaceName,
        outputDirectory);

    ImmutableSet<TargetNode<?>> orderedTargetNodes;
    if (workspaceTargetNode.getConstructorArg().srcTarget.isPresent()) {
      orderedTargetNodes = AppleBuildRules.getSchemeBuildableTargetNodes(
          projectGraph,
          Preconditions.checkNotNull(
              projectGraph.get(
                  workspaceTargetNode.getConstructorArg().srcTarget.get().getBuildTarget())));
    } else {
      orderedTargetNodes = ImmutableSet.of();
    }

    ImmutableSet<TargetNode<AppleTestDescription.Arg>> selectedTests = getOrderedTestNodes(
        projectGraph,
        orderedTargetNodes,
        extraTestBundleTargetNodes);
    ImmutableList<TargetNode<?>> buildForTestNodes =
        TopologicalSort.sort(
            projectGraph,
            Predicates.in(getTransitiveDepsAndInputs(selectedTests, orderedTargetNodes)));

    GroupedTestResults groupedTestResults = groupTests(selectedTests);
    Iterable<PBXTarget> synthesizedCombinedTestTargets = ImmutableList.of();

    ImmutableSet<BuildTarget> targetsInRequiredProjects = FluentIterable
        .from(orderedTargetNodes)
        .append(buildForTestNodes)
        .transform(HasBuildTarget.TO_TARGET)
        .toSet();
    ImmutableMap.Builder<BuildTarget, PBXTarget> buildTargetToPbxTargetMapBuilder =
        ImmutableMap.builder();
    ImmutableMap.Builder<PBXTarget, Path> targetToProjectPathMapBuilder =
        ImmutableMap.builder();

    if (combinedProject) {
      LOG.debug("Generating a combined project");
      ProjectGenerator generator = new ProjectGenerator(
          projectGraph,
          targetsInRequiredProjects,
          projectFilesystem,
          outputDirectory,
          workspaceName,
          buildFileName,
          projectGeneratorOptions)
          .setAdditionalCombinedTestTargets(groupedTestResults.groupedTests)
          .setTestsToGenerateAsStaticLibraries(groupableTests);
      combinedProjectGenerator = Optional.of(generator);
      generator.createXcodeProjects();

      workspaceGenerator.addFilePath(generator.getProjectPath(), Optional.<Path>absent());

      buildTargetToPbxTargetMapBuilder.putAll(generator.getBuildTargetToGeneratedTargetMap());
      for (PBXTarget target : generator.getBuildTargetToGeneratedTargetMap().values()) {
        targetToProjectPathMapBuilder.put(target, generator.getProjectPath());
      }
      synthesizedCombinedTestTargets = generator.getBuildableCombinedTestTargets();
      for (PBXTarget target : synthesizedCombinedTestTargets) {
        targetToProjectPathMapBuilder.put(target, generator.getProjectPath());
      }
    } else {
      ImmutableMultimap.Builder<Path, BuildTarget> projectDirectoryToBuildTargetsBuilder =
          ImmutableMultimap.builder();
      for (TargetNode<?> targetNode : projectGraph.getNodes()) {
        BuildTarget buildTarget = targetNode.getBuildTarget();
        projectDirectoryToBuildTargetsBuilder.put(buildTarget.getBasePath(), buildTarget);
      }
      ImmutableMultimap<Path, BuildTarget> projectDirectoryToBuildTargets =
          projectDirectoryToBuildTargetsBuilder.build();
      for (Path projectDirectory : projectDirectoryToBuildTargets.keySet()) {
        ImmutableSet<BuildTarget> rules = filterRulesForProjectDirectory(
            projectGraph,
            ImmutableSet.copyOf(projectDirectoryToBuildTargets.get(projectDirectory)));
        if (Sets.intersection(targetsInRequiredProjects, rules).isEmpty()) {
          continue;
        }

        ProjectGenerator generator = projectGenerators.get(projectDirectory);
        if (generator == null) {
          LOG.debug("Generating project for directory %s with targets %s", projectDirectory, rules);
          String projectName;
          if (projectDirectory.getNameCount() == 0) {
            // If we're generating a project in the root directory, use a generic name.
            projectName = "Project";
          } else {
            // Otherwise, name the project the same thing as the directory we're in.
            projectName = projectDirectory.getFileName().toString();
          }
          generator = new ProjectGenerator(
              projectGraph,
              rules,
              projectFilesystem,
              projectDirectory,
              projectName,
              buildFileName,
              projectGeneratorOptions)
              .setTestsToGenerateAsStaticLibraries(groupableTests);

          generator.createXcodeProjects();
          projectGenerators.put(projectDirectory, generator);
        } else {
          LOG.debug("Already generated project for target %s, skipping", projectDirectory);
        }

        workspaceGenerator.addFilePath(generator.getProjectPath());

        buildTargetToPbxTargetMapBuilder.putAll(generator.getBuildTargetToGeneratedTargetMap());
        for (PBXTarget target : generator.getBuildTargetToGeneratedTargetMap().values()) {
          targetToProjectPathMapBuilder.put(target, generator.getProjectPath());
        }
      }

      if (!groupedTestResults.groupedTests.isEmpty()) {
        ProjectGenerator combinedTestsProjectGenerator = new ProjectGenerator(
            projectGraph,
            ImmutableSortedSet.<BuildTarget>of(),
            projectFilesystem,
            BuildTargets.getGenPath(workspaceTargetNode.getBuildTarget(), "%s-CombinedTestBundles"),
            "_CombinedTestBundles",
            buildFileName,
            projectGeneratorOptions);
        combinedTestsProjectGenerator
            .setAdditionalCombinedTestTargets(groupedTestResults.groupedTests)
            .createXcodeProjects();
        workspaceGenerator.addFilePath(combinedTestsProjectGenerator.getProjectPath());
        for (PBXTarget target :
            combinedTestsProjectGenerator.getBuildTargetToGeneratedTargetMap().values()) {
          targetToProjectPathMapBuilder.put(target, combinedTestsProjectGenerator.getProjectPath());
        }
        synthesizedCombinedTestTargets =
            combinedTestsProjectGenerator.getBuildableCombinedTestTargets();
        for (PBXTarget target : synthesizedCombinedTestTargets) {
          targetToProjectPathMapBuilder.put(target, combinedTestsProjectGenerator.getProjectPath());
        }
        this.combinedTestsProjectGenerator = Optional.of(combinedTestsProjectGenerator);
      }
    }

    Path workspacePath = workspaceGenerator.writeWorkspace();

    final Map<BuildTarget, PBXTarget> buildTargetToTarget =
        buildTargetToPbxTargetMapBuilder.build();
    Function<TargetNode<?>, PBXTarget> targetNodeToPBXTargetTransformer =
        new Function<TargetNode<?>, PBXTarget>() {
          @Override
          public PBXTarget apply(TargetNode<?> input) {
            return Preconditions.checkNotNull(buildTargetToTarget.get(input.getBuildTarget()));
          }
        };

    SchemeGenerator schemeGenerator = new SchemeGenerator(
        projectFilesystem,
        workspaceTargetNode.getConstructorArg().srcTarget.transform(
            Functions.forMap(buildTargetToTarget)),
        Iterables.transform(orderedTargetNodes, targetNodeToPBXTargetTransformer),
        FluentIterable
            .from(buildForTestNodes)
            .transform(targetNodeToPBXTargetTransformer)
            .append(synthesizedCombinedTestTargets),
        FluentIterable
            .from(groupedTestResults.ungroupedTests)
            .transform(targetNodeToPBXTargetTransformer)
            .append(synthesizedCombinedTestTargets),
        workspaceName,
        outputDirectory.resolve(workspaceName + ".xcworkspace"),
        XcodeWorkspaceConfigDescription.getActionConfigNamesFromArg(
            workspaceTargetNode.getConstructorArg()),
        targetToProjectPathMapBuilder.build());
    schemeGenerator.writeScheme();
    this.schemeGenerator = Optional.of(schemeGenerator);

    return workspacePath;
  }

  private static ImmutableSet<BuildTarget> filterRulesForProjectDirectory(
      TargetGraph projectGraph,
      ImmutableSet<BuildTarget> projectBuildTargets) {
    // ProjectGenerator implicitly generates targets for all apple_binary rules which
    // are referred to by apple_bundle rules' 'binary' field.
    //
    // We used to support an explicit xcode_project_config() which
    // listed all dependencies explicitly, but now that we synthesize
    // one, we need to ensure we continue to only pass apple_binary
    // targets which do not belong to apple_bundle rules.
    ImmutableSet.Builder<BuildTarget> binaryTargetsInsideBundlesBuilder =
        ImmutableSet.builder();
    for (TargetNode<?> projectTargetNode : projectGraph.getAll(projectBuildTargets)) {
      if (projectTargetNode.getType() == AppleBundleDescription.TYPE) {
        AppleBundleDescription.Arg appleBundleDescriptionArg =
            (AppleBundleDescription.Arg) projectTargetNode.getConstructorArg();
        // We don't support apple_bundle rules referring to apple_binary rules
        // outside their current directory.
        Preconditions.checkState(
            appleBundleDescriptionArg.binary.getBasePath().equals(
                projectTargetNode.getBuildTarget().getBasePath()),
            "apple_bundle target %s contains reference to binary %s outside base path %s",
            projectTargetNode.getBuildTarget(),
            appleBundleDescriptionArg.binary,
            projectTargetNode.getBuildTarget().getBasePath());
        binaryTargetsInsideBundlesBuilder.add(appleBundleDescriptionArg.binary);
      }
    }
    ImmutableSet<BuildTarget> binaryTargetsInsideBundles =
        binaryTargetsInsideBundlesBuilder.build();

    // Remove all apple_binary targets which are inside bundles from
    // the rest of the build targets in the project.
    return ImmutableSet.copyOf(Sets.difference(projectBuildTargets, binaryTargetsInsideBundles));
  }

  /**
   * Find tests to run.
   *
   * @param targetGraph input target graph
   * @param orderedTargetNodes target nodes for which to fetch tests for
   * @param extraTestBundleTargets extra tests to include
   *
   * @return test targets that should be run.
   */
  private ImmutableSet<TargetNode<AppleTestDescription.Arg>> getOrderedTestNodes(
      TargetGraph targetGraph,
      ImmutableSet<TargetNode<?>> orderedTargetNodes,
      ImmutableSet<TargetNode<AppleTestDescription.Arg>> extraTestBundleTargets) {
    LOG.debug("Getting ordered test target nodes for %s", orderedTargetNodes);
    ImmutableSet.Builder<TargetNode<AppleTestDescription.Arg>> testsBuilder =
        ImmutableSet.builder();
    if (projectGeneratorOptions.contains(ProjectGenerator.Option.INCLUDE_TESTS)) {
      for (TargetNode<?> node : orderedTargetNodes) {
        if (!(node.getConstructorArg() instanceof HasTests)) {
          continue;
        }
        for (BuildTarget explicitTestTarget : ((HasTests) node.getConstructorArg()).getTests()) {
          TargetNode<?> explicitTestNode = targetGraph.get(explicitTestTarget);
          if (explicitTestNode != null) {
            Optional<TargetNode<AppleTestDescription.Arg>> castedNode =
                explicitTestNode.castArg(AppleTestDescription.Arg.class);
            if (castedNode.isPresent()) {
              testsBuilder.add(castedNode.get());
            } else {
              throw new HumanReadableException(
                  "Test target specified in '%s' is not a test: '%s'",
                  node.getBuildTarget(),
                  explicitTestTarget);
            }
          } else {
            throw new HumanReadableException(
                "Test target specified in '%s' is not in the target graph: '%s'",
                node.getBuildTarget(),
                explicitTestTarget);
          }
        }
      }
    }
    for (TargetNode<AppleTestDescription.Arg> extraTestTarget : extraTestBundleTargets) {
      testsBuilder.add(extraTestTarget);
    }
    return testsBuilder.build();
  }

  /**
   * Find transitive dependencies of inputs for building.
   *
   * @param nodes Nodes to fetch dependencies for.
   * @param excludes Nodes to exclude from dependencies list.
   * @return targets and their dependencies that should be build.
   */
  private ImmutableSet<TargetNode<?>> getTransitiveDepsAndInputs(
      Iterable<? extends TargetNode<?>> nodes,
      final ImmutableSet<TargetNode<?>> excludes) {
    return FluentIterable
        .from(nodes)
        .transformAndConcat(
            new Function<TargetNode<?>, Iterable<TargetNode<?>>>() {
              @Override
              public Iterable<TargetNode<?>> apply(TargetNode<?> input) {
                return AppleBuildRules.getRecursiveTargetNodeDependenciesOfTypes(
                    projectGraph,
                    AppleBuildRules.RecursiveDependenciesMode.BUILDING,
                    input,
                    Optional.<ImmutableSet<BuildRuleType>>absent());
              }
            })
        .append(nodes)
        .filter(
            new Predicate<TargetNode<?>>() {
              @Override
              public boolean apply(TargetNode<?> input) {
                return !excludes.contains(input) &&
                    AppleBuildRules.isXcodeTargetBuildRuleType(input.getType());
              }
            })
        .toSet();
  }

  private static ImmutableSet<TargetNode<AppleTestDescription.Arg>> getExtraTestTargetNodes(
      TargetGraph graph,
      Iterable<BuildTarget> targets) {
    ImmutableSet.Builder<TargetNode<AppleTestDescription.Arg>> builder = ImmutableSet.builder();
    for (TargetNode<?> node : graph.getAll(targets)) {
      Optional<TargetNode<AppleTestDescription.Arg>> castedNode =
          node.castArg(AppleTestDescription.Arg.class);
      if (castedNode.isPresent()) {
        builder.add(castedNode.get());
      } else {
        throw new HumanReadableException(
            "Extra test target is not a test: '%s'", node.getBuildTarget());
      }
    }
    return builder.build();
  }

  private GroupedTestResults groupTests(ImmutableSet<TargetNode<AppleTestDescription.Arg>> tests) {
    // Put tests in groups.
    ImmutableMultimap.Builder<AppleTestBundleParamsKey, TargetNode<AppleTestDescription.Arg>>
        groupsBuilder = ImmutableMultimap.builder();
    ImmutableSet.Builder<TargetNode<AppleTestDescription.Arg>> ungroupedTestsBuilder =
        ImmutableSet.builder();
    for (TargetNode<AppleTestDescription.Arg> test : tests) {
      if (groupableTests.contains(test)) {
        Preconditions.checkState(
            test.getConstructorArg().canGroup(),
            "Groupable test should actually be groupable.");
        groupsBuilder.put(
            AppleTestBundleParamsKey.fromAppleTestDescriptionArg(test.getConstructorArg()),
            test);
      } else {
        ungroupedTestsBuilder.add(test);
      }
    }
    return new GroupedTestResults(groupsBuilder.build(), ungroupedTestsBuilder.build());
  }

  private static class GroupedTestResults {
    public final ImmutableMultimap<AppleTestBundleParamsKey, TargetNode<AppleTestDescription.Arg>>
        groupedTests;
    public final ImmutableSet<TargetNode<AppleTestDescription.Arg>> ungroupedTests;

    protected GroupedTestResults(
        ImmutableMultimap<AppleTestBundleParamsKey, TargetNode<AppleTestDescription.Arg>>
            groupedTests,
        ImmutableSet<TargetNode<AppleTestDescription.Arg>> ungroupedTests) {
      this.groupedTests = groupedTests;
      this.ungroupedTests = ungroupedTests;
    }
  }
}
