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

import static com.facebook.buck.util.BuckConstant.BUILD_RULES_FILE_NAME;

import com.facebook.buck.util.DirectoryTraversal;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
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 java.io.File;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.annotation.Nullable;

/**
 * A tree of build files that reflects their tree structure in the filesystem. This makes it
 * possible to see which build files are "under" other build files.
 */
public class BuildFileTree {

  private static final Splitter PATH_SPLITTER = Splitter.on('/');
  private static final Joiner PATH_JOINER = Joiner.on('/');

  /**
   * Comparator that compares paths by number of path components and then length.
   */
  private static final Comparator<String> PATH_COMPARATOR = new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
      return ComparisonChain.start()
          .compare(Iterables.size(PATH_SPLITTER.split(a)), Iterables.size(PATH_SPLITTER.split(b)))
          .compare(a.length(), b.length())
          .compare(a, b)
          .result();
    }
  };

  private final Map<String, Node> basePathToNodeIndex;

  public BuildFileTree(Collection<BuildTarget> targets) {
    this(collectBasePaths(targets));
  }

  private static Iterable<String> collectBasePaths(Collection<BuildTarget> targets) {
    Preconditions.checkNotNull(targets);

    return Iterables.transform(targets, new Function<BuildTarget, String>() {
      @Override public String apply(BuildTarget buildTarget) {
        return buildTarget.getBasePath();
      }
    });
  }

  public BuildFileTree(Iterable<String> basePaths) {
    TreeSet<String> allBasePaths = Sets.newTreeSet(PATH_COMPARATOR);
    for (String basePath : basePaths) {
      allBasePaths.add(basePath);
    }

    // Initialize basePathToNodeIndex with a Node that corresponds to the empty string. This ensures
    // that findParent() will always return a non-null Node because the empty string is a prefix of
    // all base paths.
    basePathToNodeIndex = Maps.newHashMap();
    Node root = new Node("");
    basePathToNodeIndex.put("", root);

    // Build up basePathToNodeIndex in a breadth-first manner.
    for (String basePath : allBasePaths) {
      if ("".equals(basePath)) {
        continue;
      }

      Node child = new Node(basePath);
      Node parent = findParent(child, basePathToNodeIndex);
      parent.addChild(child);
      basePathToNodeIndex.put(basePath, child);
    }
  }

  public static BuildFileTree constructBuildFileTree(ProjectFilesystem filesystem) {
    File root = filesystem.getProjectRoot();

    final Set<String> targets = Sets.newHashSet();

    DirectoryTraversal traversal = new DirectoryTraversal(root, filesystem.getIgnorePaths()) {
      @Override public void visit(File file, String relativePath) {
        if (!BUILD_RULES_FILE_NAME.equals(file.getName())) {
          return;
        }

        int index = Math.max(0, relativePath.lastIndexOf("/"));
        String baseName = relativePath.substring(0, index);
        targets.add(baseName);
      }
    };
    traversal.traverse();

    return new BuildFileTree(targets);
  }

  public String getBasePathOfAncestorTarget(String filePath) {
    Node node = new Node(filePath);
    Node parent = findParent(node, basePathToNodeIndex);
    if (parent != null) {
      return parent.basePath;
    } else {
      return "";
    }
  }

  /**
   * @return Iterable of relative paths to the BuildTarget's directory that contain their own build
   *     files. No element in the Iterable is a prefix of any other element in the Iterable.
   */
  public Iterable<String> getChildPaths(BuildTarget buildTarget) {
    String basePath = buildTarget.getBasePath();
    return getChildPaths(basePath);
  }

  @VisibleForTesting
  Iterable<String> getChildPaths(String basePath) {
    Node node = basePathToNodeIndex.get(basePath);
    if (node.children == null) {
      return ImmutableList.of();
    } else {
      int basePathLength = basePath.length();
      final int lengthOfPrefixToStrip = basePathLength == 0 ? basePathLength : basePathLength + 1;
      return Iterables.transform(node.children, new Function<Node, String>() {
        @Override
        public String apply(Node child) {
          return child.basePath.substring(lengthOfPrefixToStrip);
        }
      });
    }
  }

  /**
   * Finds the parent Node of the specified child Node.
   * @param child whose parent is sought in {@code basePathToNodeIndex}.
   * @param basePathToNodeIndex Map that must contain a Node with a basePath that is a prefix of
   *     {@code child}'s basePath.
   * @return the Node in {@code basePathToNodeIndex} with the longest basePath that is a prefix of
   *     {@code child}'s basePath.
   */
  private static Node findParent(Node child, Map<String, Node> basePathToNodeIndex) {
    ImmutableList<String> parts = ImmutableList.copyOf(child.basePath.split("/"));
    for (int numParts = parts.size() - 1; numParts > 0; numParts--) {
      List<String> partsCandidate = parts.subList(0, numParts);
      String candidateBasePath = PATH_JOINER.join(partsCandidate);
      Node candidate = basePathToNodeIndex.get(candidateBasePath);
      if (candidate != null) {
        return candidate;
      }
    }

    return basePathToNodeIndex.get("");
  }

  /** Represents a build file in the project directory. */
  private static class Node {

    /** Result of {@link BuildTarget#getBasePath()}. */
    private final String basePath;

    /** List of child nodes: created lazily to save memory. */
    @Nullable
    private List<Node> children;

    Node(String basePath) {
      this.basePath = basePath;
    }

    void addChild(Node node) {
      if (children == null) {
        children = Lists.newArrayList();
      }
      children.add(node);
    }
  }
}
