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

import com.facebook.buck.rules.JavaPackageFinder;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;

import java.io.File;
import java.util.Deque;

public class DefaultJavaPackageFinder implements JavaPackageFinder {

  /**
   * Each element in this set is a path prefix from the root of the repository.
   * <p>
   * Elements in this set are ordered opposite to their natural order such that if one element is a
   * prefix of another element in the Set, the longer String will appear first. This makes it
   * possible to iterate over the elements in the set in order, comparing to a test element, such
   * that the longest matching prefix matches the test element.
   * <p>
   * Every element in this set ends with a slash.
   */
  private final ImmutableSortedSet<String> pathsFromRoot;

  private final ImmutableSet<String> pathElements;

  public DefaultJavaPackageFinder(ImmutableSortedSet<String> pathsFromRoot,
      ImmutableSet<String> pathElements) {
    this.pathsFromRoot = pathsFromRoot;
    this.pathElements = pathElements;
  }

  @Override
  public String findJavaPackageFolderForPath(String pathRelativeToProjectRoot) {
    for (String pathFromRoot : pathsFromRoot) {
      if (pathRelativeToProjectRoot.startsWith(pathFromRoot)) {
        int lastSlashIndex = pathRelativeToProjectRoot.lastIndexOf('/');
        Preconditions.checkState(lastSlashIndex >= 0,
            "Because pathFromRoot must end with a slash and is a prefix of " +
            "pathRelativeToProjectRoot, pathRelativeToProjectRoot must contain a slash.");
        return pathRelativeToProjectRoot.substring(pathFromRoot.length(), lastSlashIndex + 1);
      }
    }

    File directory;
    if (pathRelativeToProjectRoot.endsWith("/")) {
      directory = new File(pathRelativeToProjectRoot);
    } else {
      directory = new File(pathRelativeToProjectRoot).getParentFile();
    }
    Deque<String> parts = Lists.newLinkedList();
    while (directory != null && !pathElements.contains(directory.getName())) {
      parts.addFirst(directory.getName());
      directory = directory.getParentFile();
    }

    if (!parts.isEmpty()) {
      return Joiner.on('/').join(parts) + '/';
    } else {
      return "";
    }
  }

  public ImmutableSortedSet<String> getPathsFromRoot() {
    return pathsFromRoot;
  }

  public ImmutableSet<String> getPathElements() {
    return pathElements;
  }

  /**
   * @param pathPatterns elements that start with a slash must be prefix patterns; all other
   *     elements indicate individual directory names (and therefore cannot contain slashes).
   */
  public static DefaultJavaPackageFinder createDefaultJavaPackageFinder(
      Iterable<String> pathPatterns) {
    ImmutableSortedSet.Builder<String> pathsFromRoot = ImmutableSortedSet.reverseOrder();
    ImmutableSet.Builder<String> pathElements = ImmutableSet.builder();
    for (String pattern : pathPatterns) {
      if (pattern.charAt(0) == '/') {
        // Strip the leading slash.
        pattern = pattern.substring(1);

        // Ensure there is a trailing slash, unless it is an empty string.
        if (!pattern.isEmpty() && !pattern.endsWith("/")) {
          pattern = pattern + "/";
        }
        pathsFromRoot.add(pattern);
      } else {
        if (pattern.contains("/")) {
          throw new HumanReadableException(
              "Path pattern that does not start with a slash cannot contain a slash: %s", pattern);
        }
        pathElements.add(pattern);
      }
    }
    return new DefaultJavaPackageFinder(pathsFromRoot.build(), pathElements.build());
  }

  @Override
  public String findJavaPackageForPath(String pathRelativeToProjectRoot) {
    String folder = findJavaPackageFolderForPath(pathRelativeToProjectRoot);
    if (!folder.isEmpty()) {
      // Strip the trailing slash and replace the remaining slashes with dots.
      return folder.substring(0, folder.length() - 1).replace('/', '.');
    } else {
      return "";
    }
  }
}
