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

import com.facebook.buck.io.MorePaths;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.HasOutputName;
import com.facebook.buck.util.HumanReadableException;
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.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

public class SourcePathResolver {

  private final BuildRuleResolver ruleResolver;

  public SourcePathResolver(BuildRuleResolver ruleResolver) {
    this.ruleResolver = ruleResolver;
  }

  public Path getPath(SourcePath sourcePath) {
    if (sourcePath instanceof PathSourcePath) {
      return ((PathSourcePath) sourcePath).getRelativePath();
    }
    Preconditions.checkArgument(sourcePath instanceof BuildTargetSourcePath);
    BuildTargetSourcePath buildTargetSourcePath = (BuildTargetSourcePath) sourcePath;
    Optional<Path> resolvedPath = buildTargetSourcePath.getResolvedPath();
    if (resolvedPath.isPresent()) {
      return resolvedPath.get();
    }

    Path path = ruleResolver.getRule(buildTargetSourcePath.getTarget()).getPathToOutputFile();
    if (path == null) {
      throw new HumanReadableException(
          "No known output for: %s",
          buildTargetSourcePath.getTarget());
    }

    return path;
  }

  public Function<SourcePath, Path> getPathFunction() {
    return new Function<SourcePath, Path>() {
      @Override
      public Path apply(SourcePath input) {
        return getPath(input);
      }
    };
  }

  public ImmutableList<Path> getAllPaths(Iterable<? extends SourcePath> sourcePaths) {
    // Maintain ordering and duplication if necessary.
    return FluentIterable.from(sourcePaths).transform(getPathFunction()).toList();
  }

  public <T> ImmutableMap<T, Path> getMappedPaths(Map<T, SourcePath> sourcePathMap) {
    ImmutableMap.Builder<T, Path> paths = ImmutableMap.builder();
    for (ImmutableMap.Entry<T, SourcePath> entry : sourcePathMap.entrySet()) {
      paths.put(entry.getKey(), getPath(entry.getValue()));
    }
    return paths.build();
  }

  /**
   * @return An {@link Optional} containing the {@link BuildRule} whose output {@code sourcePath}
   *         refers to, or {@code absent} if {@code sourcePath} doesn't refer to the output of a
   *         {@link BuildRule}.
   */
  public Optional<BuildRule> getRule(SourcePath sourcePath) {
    if (sourcePath instanceof PathSourcePath) {
      return Optional.absent();
    }
    Preconditions.checkState(sourcePath instanceof BuildTargetSourcePath);
    return Optional.of(ruleResolver.getRule(((BuildTargetSourcePath) sourcePath).getTarget()));
  }

  /**
   * @return An {@link Optional} containing the {@link Path} the {@code sourcePath} refers to if it
   *         doesn't refer to the output of a {@link BuildRule}, or {@code absent} if it does.
   */
  public Optional<Path> getRelativePath(SourcePath sourcePath) {
    if (sourcePath instanceof BuildTargetSourcePath) {
      return Optional.absent();
    }
    Preconditions.checkState(sourcePath instanceof PathSourcePath);
    return Optional.of(((PathSourcePath) sourcePath).getRelativePath());
  }

  /**
   * Resolved the logical names for a group of SourcePath objects into a map, throwing an
   * error on duplicates.
   */
  public ImmutableMap<String, SourcePath> getSourcePathNames(
      BuildTarget target,
      String parameter,
      Iterable<SourcePath> sourcePaths) {
    return getSourcePathNames(target, parameter, sourcePaths, Functions.<SourcePath>identity());
  }

  /**
   * Resolves the logical names for a group of objects that have a SourcePath into a map,
   * throwing an error on duplicates.
   */
  public <T> ImmutableMap<String, T> getSourcePathNames(
      BuildTarget target,
      String parameter,
      Iterable<T> objects,
      Function<T, SourcePath> objectSourcePathFunction) {

    Map<String, T> resolved = Maps.newHashMap();

    for (T object : objects) {
      SourcePath path = objectSourcePathFunction.apply(object);
      String name = getSourcePathName(target, path);
      T old = resolved.put(name, object);
      if (old != null) {
        throw new HumanReadableException(String.format(
            "%s: parameter '%s': duplicate entries for '%s'",
            target,
            parameter,
            name));
      }
    }

    return ImmutableMap.copyOf(resolved);
  }

  public String getSourcePathName(BuildTarget target, SourcePath sourcePath) {
    if (sourcePath instanceof BuildTargetSourcePath) {
      return getNameForRule(ruleResolver.getRule(((BuildTargetSourcePath) sourcePath).getTarget()));
    }
    Preconditions.checkArgument(sourcePath instanceof PathSourcePath);
    Path path = ((PathSourcePath) sourcePath).getRelativePath();
    return MorePaths.relativize(target.getBasePath(), path).toString();
  }

  private String getNameForRule(BuildRule rule) {

    // If this build rule implements `HasOutputName`, then return the output name
    // it provides.
    if (rule instanceof HasOutputName) {
      HasOutputName hasOutputName = (HasOutputName) rule;
      return hasOutputName.getOutputName();
    }

    // Otherwise, fall back to using the short name of rule's build target.
    return rule.getBuildTarget().getShortName();
  }

  /**
   * Takes an {@link Iterable} of {@link SourcePath} objects and filters those that are suitable to
   * be returned by {@link com.facebook.buck.rules.AbstractBuildRule#getInputsToCompareToOutput()}.
   */
  public ImmutableCollection<Path> filterInputsToCompareToOutput(
      Iterable<? extends SourcePath> sources) {
    // Currently, the only implementation of SourcePath that should be included in the Iterable
    // returned by getInputsToCompareToOutput() is FileSourcePath, so it is safe to filter by that
    // and then use .asReference() to get its path.
    //
    // BuildTargetSourcePath should not be included in the output because it refers to a generated
    // file, and generated files are not hashed as part of a RuleKey.
    return FluentIterable.from(sources)
        .filter(PathSourcePath.class)
        .transform(
            new Function<PathSourcePath, Path>() {
              @Override
              public Path apply(PathSourcePath input) {
                return input.getRelativePath();
              }
            })
        .toList();
  }

  public ImmutableCollection<Path> filterInputsToCompareToOutput(SourcePath... sources) {
    return filterInputsToCompareToOutput(Arrays.asList(sources));
  }

  public Collection<BuildRule> filterBuildRuleInputs(
      Iterable<? extends SourcePath> sources) {
    return FluentIterable.from(sources)
        .filter(BuildTargetSourcePath.class)
        .transform(
            new Function<BuildTargetSourcePath, BuildRule>() {
              @Override
              public BuildRule apply(BuildTargetSourcePath input) {
                return ruleResolver.getRule(input.getTarget());
              }
            })
        .toList();
  }
}
