/*
 * 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.model.BuildFileTree;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.coercer.TypeCoercerFactory;
import com.facebook.buck.util.ExceptionWithHumanReadableMessage;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;

import java.lang.reflect.Field;
import java.nio.file.Path;

/**
 * A {@link TargetNode} represents a node in the target graph which is created by the
 * {@link com.facebook.buck.parser.Parser} as a result of parsing BUCK files in a project. It is
 * responsible for processing the raw (python) inputs of a build rule, and gathering any build
 * targets and paths referenced from those inputs.
 */
public class TargetNode<T> implements Comparable<TargetNode<?>>, HasBuildTarget {

  private final BuildRuleFactoryParams ruleFactoryParams;
  private final Description<T> description;

  private final T constructorArg;

  private final ImmutableSet<Path> pathsReferenced;
  private final ImmutableSet<BuildTarget> declaredDeps;
  private final ImmutableSortedSet<BuildTarget> extraDeps;
  private final ImmutableSet<BuildTargetPattern> visibilityPatterns;

  @SuppressWarnings("unchecked")
  public TargetNode(
      Description<T> description,
      T constructorArg,
      BuildRuleFactoryParams params,
      ImmutableSet<BuildTarget> declaredDeps,
      ImmutableSet<BuildTargetPattern> visibilityPatterns)
      throws NoSuchBuildTargetException, InvalidSourcePathInputException {
    this.description = description;
    this.constructorArg = constructorArg;
    this.ruleFactoryParams = params;

    final ImmutableSet.Builder<Path> paths = ImmutableSet.builder();
    final ImmutableSortedSet.Builder<BuildTarget> extraDeps = ImmutableSortedSet.naturalOrder();

    // Scan the input to find possible BuildTargets, necessary for loading dependent rules.
    TypeCoercerFactory typeCoercerFactory = new TypeCoercerFactory();
    T arg = description.createUnpopulatedConstructorArg();
    for (Field field : arg.getClass().getFields()) {
      ParamInfo<T> info = new ParamInfo<>(typeCoercerFactory, field);
      if (info.isDep() &&
          info.hasElementTypes(BuildTarget.class, SourcePath.class, Path.class)) {
        detectBuildTargetsAndPathsForConstructorArg(extraDeps, paths, info, constructorArg);
      }
    }

    if (description instanceof ImplicitDepsInferringDescription) {
      extraDeps
          .addAll(
              ((ImplicitDepsInferringDescription<T>) description)
                  .findDepsForTargetFromConstructorArgs(params.target, constructorArg));
    }

    this.extraDeps = ImmutableSortedSet.copyOf(Sets.difference(extraDeps.build(), declaredDeps));
    this.pathsReferenced = ruleFactoryParams.enforceBuckPackageBoundary()
        ? verifyPaths(paths.build())
        : paths.build();

    this.declaredDeps = declaredDeps;
    this.visibilityPatterns = visibilityPatterns;
  }

  public Description<T> getDescription() {
    return description;
  }

  public BuildRuleType getType() {
    return description.getBuildRuleType();
  }

  public T getConstructorArg() {
    return constructorArg;
  }

  @Override
  public BuildTarget getBuildTarget() {
    return ruleFactoryParams.target;
  }

  public ImmutableSet<Path> getInputs() {
    return pathsReferenced;
  }

  public ImmutableSet<BuildTarget> getDeclaredDeps() {
    return declaredDeps;
  }

  public ImmutableSet<BuildTarget> getExtraDeps() {
    return extraDeps;
  }

  public ImmutableSet<BuildTarget> getDeps() {
    ImmutableSet.Builder<BuildTarget> builder = ImmutableSet.builder();
    builder.addAll(getDeclaredDeps());
    builder.addAll(getExtraDeps());
    return builder.build();
  }

  public BuildRuleFactoryParams getRuleFactoryParams() {
    return ruleFactoryParams;
  }

  /**
   * TODO(agallagher): It'd be nice to eventually move this implementation to an
   * `AbstractDescription` base class, so that the various types of descriptions
   * can install their own implementations.  However, we'll probably want to move
   * most of what is now `BuildRuleParams` to `DescriptionParams` and set them up
   * while building the target graph.
   */
  public boolean isVisibleTo(BuildTarget other) {
    return BuildTargets.isVisibleTo(
        getBuildTarget(),
        visibilityPatterns,
        other);
  }

  public void checkVisibility(BuildTarget other) {
    if (!isVisibleTo(other)) {
      throw new HumanReadableException(
          "%s depends on %s, which is not visible",
          other,
          getBuildTarget());
    }
  }

  /**
   * Type safe checked cast of the constructor arg.
   */
  @SuppressWarnings("unchecked")
  public <U> Optional<TargetNode<U>> castArg(Class<U> cls) {
    if (cls.isInstance(constructorArg)) {
      return Optional.of((TargetNode<U>) this);
    } else {
      return Optional.absent();
    }
  }

  private void detectBuildTargetsAndPathsForConstructorArg(
      final ImmutableSet.Builder<BuildTarget> depsBuilder,
      final ImmutableSet.Builder<Path> pathsBuilder,
      ParamInfo<T> info,
      T constructorArg) throws NoSuchBuildTargetException {
    // We'll make no test for optionality here. Let's assume it's done elsewhere.

    try {
      info.traverse(
          new ParamInfo.Traversal() {
            @Override
            public void traverse(Object object) {
              if (object instanceof PathSourcePath) {
                pathsBuilder.add(((PathSourcePath) object).getRelativePath());
              } else if (object instanceof BuildTargetSourcePath) {
                depsBuilder.add(((BuildTargetSourcePath) object).getTarget());
              } else if (object instanceof Path) {
                pathsBuilder.add((Path) object);
              } else if (object instanceof BuildTarget) {
                depsBuilder.add((BuildTarget) object);
              }
            }
          },
          constructorArg);
    } catch (RuntimeException e) {
      if (e.getCause() instanceof NoSuchBuildTargetException) {
        throw (NoSuchBuildTargetException) e.getCause();
      }
    }
  }

  private ImmutableSet<Path> verifyPaths(ImmutableSet<Path> paths)
      throws InvalidSourcePathInputException {
    Path basePath = getBuildTarget().getBasePath();
    BuildFileTree buildFileTree = ruleFactoryParams.getBuildFileTree();

    for (Path path : paths) {
      if (!basePath.toString().isEmpty() && !path.startsWith(basePath)) {
        throw new InvalidSourcePathInputException(
            "'%s' in '%s' refers to a parent directory.",
            basePath.relativize(path),
            getBuildTarget());
      }

      Optional<Path> ancestor = buildFileTree.getBasePathOfAncestorTarget(path);
      if (!ancestor.isPresent() || !ancestor.get().equals(basePath)) {
        throw new InvalidSourcePathInputException(
            "'%s' in '%s' crosses a buck package boundary. Find the nearest BUCK file in the " +
                "directory that contains this file and refer to the rule referencing the desired" +
                "file.",
            path,
            getBuildTarget());
      }
    }

    return paths;
  }

  @Override
  public int compareTo(TargetNode<?> o) {
    return getBuildTarget().compareTo(o.getBuildTarget());
  }

  @Override
  public final boolean equals(Object obj) {
    if (!(obj instanceof TargetNode<?>)) {
      return false;
    }
    TargetNode<?> that = (TargetNode<?>) obj;
    return this.getBuildTarget().equals(that.getBuildTarget());
  }

  @Override
  public final int hashCode() {
    return getBuildTarget().hashCode();
  }

  @Override
  public final String toString() {
    return getBuildTarget().getFullyQualifiedName();
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  public TargetNode<T> with(
      Description<T> description,
      T constructorArg,
      BuildRuleFactoryParams ruleFactoryParams,
      ImmutableSet declaredDeps,
      ImmutableSet<BuildTargetPattern> visibilityPatterns) {
    try {
      return new TargetNode(
          description,
          constructorArg,
          ruleFactoryParams,
          declaredDeps,
          visibilityPatterns);
    } catch (InvalidSourcePathInputException | NoSuchBuildTargetException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Return a copy of the current TargetNode, with the {@link Description} used for creating
   * {@link BuildRule} instances switched out.
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public TargetNode<?> withDescription(Description<?> description) {
    try {
      return new TargetNode(
          description,
          constructorArg,
          ruleFactoryParams,
          declaredDeps,
          visibilityPatterns);
    } catch (InvalidSourcePathInputException | NoSuchBuildTargetException e) {
      // This is extremely unlikely to happen --- we've already created a TargetNode with these
      // values before.
      throw new RuntimeException(e);
    }
  }

  public TargetNode<T> withConstructorArg(T constructorArg) {
    return with(description, constructorArg, ruleFactoryParams, declaredDeps, visibilityPatterns);
  }

  public TargetNode<T> withBuildTarget(BuildTarget buildTarget) {
    return with(
        description,
        constructorArg,
        ruleFactoryParams.withBuildTarget(buildTarget),
        declaredDeps,
        visibilityPatterns);
  }

  @SuppressWarnings("serial")
  public static class InvalidSourcePathInputException extends Exception
      implements ExceptionWithHumanReadableMessage{

    private InvalidSourcePathInputException(String message, Object...objects) {
      super(String.format(message, objects));
    }

    @Override
    public String getHumanReadableErrorMessage() {
      return getMessage();
    }
  }
}
