/*
 * Copyright 2013-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.io.ProjectFilesystem;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.SourceWithFlags;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Multimap;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;

/**
 * Common conversion functions from raw Description Arg specifications.
 */
public class RuleUtils {

  /** Utility class: do not instantiate. */
  private RuleUtils() {}

  public static ImmutableList<GroupedSource> createGroupsFromSourcePaths(
      SourcePathResolver resolver,
      Iterable<SourceWithFlags> sources,
      Iterable<SourcePath> publicHeaders,
      Iterable<SourcePath> privateHeaders) {
    Path rootPath = Paths.get("root");

    ImmutableMultimap.Builder<Path, GroupedSource> entriesBuilder = ImmutableMultimap.builder();
    for (SourceWithFlags sourceWithFlags : sources) {
      Path path = rootPath.resolve(resolver.getPath(sourceWithFlags.getSourcePath()));
      GroupedSource groupedSource = GroupedSource.ofSourceWithFlags(sourceWithFlags);
      entriesBuilder.put(Preconditions.checkNotNull(path.getParent()), groupedSource);
    }
    for (SourcePath publicHeader : publicHeaders) {
      Path path = rootPath.resolve(resolver.getPath(publicHeader));
      GroupedSource groupedSource = GroupedSource.ofPublicHeader(publicHeader);
      entriesBuilder.put(Preconditions.checkNotNull(path.getParent()), groupedSource);
    }
    for (SourcePath privateHeader : privateHeaders) {
      Path path = rootPath.resolve(resolver.getPath(privateHeader));
      GroupedSource groupedSource = GroupedSource.ofPrivateHeader(privateHeader);
      entriesBuilder.put(Preconditions.checkNotNull(path.getParent()), groupedSource);
    }
    ImmutableMultimap<Path, GroupedSource> entries = entriesBuilder.build();

    ImmutableMultimap.Builder<Path, String> subgroupsBuilder = ImmutableMultimap.builder();
    for (Path groupPath : entries.keys()) {
      Path parent = groupPath.getParent();
      while (parent != null) {
        subgroupsBuilder.put(parent, groupPath.getFileName().toString());
        groupPath = parent;
        parent = groupPath.getParent();
      }
    }
    ImmutableMultimap<Path, String> subgroups = subgroupsBuilder.build();

    GroupedSourceNameComparator groupedSourceNameComparator =
        new GroupedSourceNameComparator(resolver);

    ImmutableList<GroupedSource> groupedSources =
        createGroupsFromEntryMaps(
            subgroups,
            entries,
            groupedSourceNameComparator,
            rootPath);

    // Remove the longest common prefix from all paths.
    while (groupedSources.size() == 1 &&
        groupedSources.get(0).getType() == GroupedSource.Type.SOURCE_GROUP) {
      groupedSources = ImmutableList.copyOf(groupedSources.get(0).getSourceGroup().get());
    }

    return groupedSources;
  }

  static class GroupedSourceNameComparator implements Comparator<GroupedSource> {
    private final SourcePathResolver pathResolver;

    public GroupedSourceNameComparator(SourcePathResolver pathResolver) {
      this.pathResolver = pathResolver;
    }

    @Override
    public int compare(GroupedSource source1, GroupedSource source2) {
      String name1 = source1.getName(pathResolver);
      String name2 = source2.getName(pathResolver);
      return name1.compareTo(name2);
    }

  }

  @VisibleForTesting
  static ImmutableList<GroupedSource> createGroupsFromEntryMaps(
      Multimap<Path, String> subgroups,
      Multimap<Path, GroupedSource> entries,
      Comparator<GroupedSource> comparator,
      Path groupPath) {
    ImmutableList.Builder<GroupedSource> groupBuilder = ImmutableList.builder();

    for (String subgroupName : ImmutableSortedSet.copyOf(subgroups.get(groupPath))) {
      Path subgroupPath = groupPath.resolve(subgroupName);
      groupBuilder.add(
          GroupedSource.ofSourceGroup(
              subgroupName,
              createGroupsFromEntryMaps(subgroups, entries, comparator, subgroupPath)));
    }

    SortedSet<GroupedSource> sortedEntries =
        ImmutableSortedSet.copyOf(comparator, entries.get(groupPath));
    for (GroupedSource groupedSource : sortedEntries) {
      groupBuilder.add(groupedSource);
    }

    return groupBuilder.build().asList();
  }

  public static Supplier<ImmutableCollection<Path>> subpathsOfPathsSupplier(
      final ProjectFilesystem projectFilesystem,
      final Set<Path> dirs) {
    return Suppliers.memoize(
        new Supplier<ImmutableCollection<Path>>() {
          @Override
          public ImmutableCollection<Path> get() {
            ImmutableSortedSet.Builder<Path> paths = ImmutableSortedSet.naturalOrder();
            for (Path dir : dirs) {
              try {
                paths.addAll(projectFilesystem.getFilesUnderPath(dir));
              } catch (IOException e) {
                throw new HumanReadableException(e, "Error traversing directory: %s.", dir);
              }
            }
            return paths.build();
          }
        });
  }
}
