/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.java.sync.source;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.idea.blaze.base.async.executor.TransientExecutor;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.TargetKey;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.scope.scopes.TimingScope;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.base.util.PackagePrefixCalculator;
import com.google.idea.blaze.java.sync.model.BlazeContentEntry;
import com.google.idea.blaze.java.sync.model.BlazeSourceDirectory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * This is a utility class for calculating the java sources and their package prefixes given a
 * module and its Blaze {@link ArtifactLocation} list.
 */
public final class SourceDirectoryCalculator {

  private static final Logger logger = Logger.getInstance(SourceDirectoryCalculator.class);

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

  private static final JavaPackageReader generatedFileJavaPackageReader =
      new FilePathJavaPackageReader();
  private final ListeningExecutorService executorService = MoreExecutors.newDirectExecutorService();
  private final ListeningExecutorService packageReaderExecutorService =
      MoreExecutors.listeningDecorator(new TransientExecutor(16));

  public ImmutableList<BlazeContentEntry> calculateContentEntries(
      Project project,
      BlazeContext context,
      WorkspaceRoot workspaceRoot,
      ArtifactLocationDecoder artifactLocationDecoder,
      Collection<WorkspacePath> rootDirectories,
      Collection<SourceArtifact> sources,
      Map<TargetKey, ArtifactLocation> javaPackageManifests) {

    ManifestFilePackageReader manifestFilePackageReader =
        Scope.push(
            context,
            (childContext) -> {
              childContext.push(new TimingScope("ReadPackageManifests"));
              Map<TargetKey, Map<ArtifactLocation, String>> manifestMap =
                  PackageManifestReader.getInstance()
                      .readPackageManifestFiles(
                          project,
                          childContext,
                          artifactLocationDecoder,
                          javaPackageManifests,
                          packageReaderExecutorService);
              return new ManifestFilePackageReader(manifestMap);
            });

    final List<JavaPackageReader> javaPackageReaders =
        Lists.newArrayList(
            manifestFilePackageReader,
            JavaSourcePackageReader.getInstance(),
            generatedFileJavaPackageReader);

    Collection<SourceArtifact> nonGeneratedSources = filterGeneratedArtifacts(sources);

    // Sort artifacts and excludes into their respective workspace paths
    Multimap<WorkspacePath, SourceArtifact> sourcesUnderDirectoryRoot =
        sortArtifactLocationsByRootDirectory(context, rootDirectories, nonGeneratedSources);

    List<BlazeContentEntry> result = Lists.newArrayList();
    Scope.push(
        context,
        (childContext) -> {
          childContext.push(new TimingScope("CalculateSourceDirectories"));
          for (WorkspacePath workspacePath : rootDirectories) {
            File contentRoot = workspaceRoot.fileForPath(workspacePath);
            ImmutableList<BlazeSourceDirectory> sourceDirectories =
                calculateSourceDirectoriesForContentRoot(
                    context,
                    workspaceRoot,
                    artifactLocationDecoder,
                    workspacePath,
                    sourcesUnderDirectoryRoot.get(workspacePath),
                    javaPackageReaders);
            if (!sourceDirectories.isEmpty()) {
              result.add(new BlazeContentEntry(contentRoot, sourceDirectories));
            }
          }
          result.sort(Comparator.comparing(lhs -> lhs.contentRoot));
        });
    return ImmutableList.copyOf(result);
  }

  private Collection<SourceArtifact> filterGeneratedArtifacts(
      Collection<SourceArtifact> artifactLocations) {
    return artifactLocations
        .stream()
        .filter(sourceArtifact -> sourceArtifact.artifactLocation.isSource())
        .collect(Collectors.toList());
  }

  private static Multimap<WorkspacePath, SourceArtifact> sortArtifactLocationsByRootDirectory(
      BlazeContext context,
      Collection<WorkspacePath> rootDirectories,
      Collection<SourceArtifact> sources) {

    Multimap<WorkspacePath, SourceArtifact> result = ArrayListMultimap.create();

    for (SourceArtifact sourceArtifact : sources) {
      WorkspacePath foundWorkspacePath =
          rootDirectories
              .stream()
              .filter(
                  rootDirectory ->
                      isUnderRootDirectory(
                          rootDirectory, sourceArtifact.artifactLocation.getRelativePath()))
              .findFirst()
              .orElse(null);

      if (foundWorkspacePath != null) {
        result.put(foundWorkspacePath, sourceArtifact);
      } else if (sourceArtifact.artifactLocation.isSource()) {
        ArtifactLocation sourceFile = sourceArtifact.artifactLocation;
        String message =
            String.format(
                "Did not add %s. You're probably using a java file from outside the workspace"
                    + " that has been exported using export_files. Don't do that.",
                sourceFile);
        IssueOutput.warn(message).submit(context);
      }
    }
    return result;
  }

  private static boolean isUnderRootDirectory(WorkspacePath rootDirectory, String relativePath) {
    if (rootDirectory.isWorkspaceRoot()) {
      return true;
    }
    String rootDirectoryString = rootDirectory.toString();
    return relativePath.startsWith(rootDirectoryString)
        && (relativePath.length() == rootDirectoryString.length()
            || (relativePath.charAt(rootDirectoryString.length()) == '/'));
  }

  /** Calculates all source directories for a single content root. */
  private ImmutableList<BlazeSourceDirectory> calculateSourceDirectoriesForContentRoot(
      BlazeContext context,
      WorkspaceRoot workspaceRoot,
      ArtifactLocationDecoder artifactLocationDecoder,
      WorkspacePath directoryRoot,
      Collection<SourceArtifact> sourceArtifacts,
      Collection<JavaPackageReader> javaPackageReaders) {

    // Split out java-like files
    Predicate<ArtifactLocation> isSourceFile = JavaLikeLanguage.getSourceFileMatcher();
    List<SourceArtifact> javaArtifacts = Lists.newArrayList();
    for (SourceArtifact sourceArtifact : sourceArtifacts) {
      if (isSourceFile.test(sourceArtifact.artifactLocation)) {
        javaArtifacts.add(sourceArtifact);
      }
    }

    List<BlazeSourceDirectory> result = Lists.newArrayList();

    // Add java source directories
    calculateJavaSourceDirectories(
        context,
        workspaceRoot,
        artifactLocationDecoder,
        directoryRoot,
        javaArtifacts,
        javaPackageReaders,
        result);

    Collections.sort(result, BlazeSourceDirectory.COMPARATOR);
    return ImmutableList.copyOf(result);
  }

  /** Adds the java source directories. */
  private void calculateJavaSourceDirectories(
      BlazeContext context,
      WorkspaceRoot workspaceRoot,
      ArtifactLocationDecoder artifactLocationDecoder,
      WorkspacePath directoryRoot,
      Collection<SourceArtifact> javaArtifacts,
      Collection<JavaPackageReader> javaPackageReaders,
      Collection<BlazeSourceDirectory> result) {

    List<SourceRoot> sourceRootsPerFile = Lists.newArrayList();

    // Get java sources
    List<ListenableFuture<SourceRoot>> sourceRootFutures = Lists.newArrayList();
    for (final SourceArtifact sourceArtifact : javaArtifacts) {
      ListenableFuture<SourceRoot> future =
          executorService.submit(
              () ->
                  sourceRootForJavaSource(
                      context, artifactLocationDecoder, sourceArtifact, javaPackageReaders));
      sourceRootFutures.add(future);
    }
    try {
      for (SourceRoot sourceRoot : Futures.allAsList(sourceRootFutures).get()) {
        if (sourceRoot != null) {
          sourceRootsPerFile.add(sourceRoot);
        }
      }
    } catch (ExecutionException | InterruptedException e) {
      logger.error(e);
      throw new IllegalStateException("Could not read sources");
    }

    // Sort source roots into their respective directories
    Multimap<WorkspacePath, SourceRoot> sourceDirectoryToSourceRoots = HashMultimap.create();
    for (SourceRoot sourceRoot : sourceRootsPerFile) {
      sourceDirectoryToSourceRoots.put(sourceRoot.workspacePath, sourceRoot);
    }

    // Create a mapping from directory to package prefix
    Map<WorkspacePath, SourceRoot> workspacePathToSourceRoot = Maps.newHashMap();
    for (WorkspacePath workspacePath : sourceDirectoryToSourceRoots.keySet()) {
      Collection<SourceRoot> sources = sourceDirectoryToSourceRoots.get(workspacePath);
      Multiset<String> packages = HashMultiset.create();

      for (SourceRoot source : sources) {
        packages.add(source.packagePrefix);
      }

      final String directoryPackagePrefix;
      // Common case -- all source files agree on a single package
      if (packages.elementSet().size() == 1) {
        directoryPackagePrefix = packages.elementSet().iterator().next();
      } else {
        String preferredPackagePrefix = PackagePrefixCalculator.packagePrefixOf(workspacePath);
        directoryPackagePrefix = pickMostFrequentlyOccurring(packages, preferredPackagePrefix);
      }

      SourceRoot candidateRoot = new SourceRoot(workspacePath, directoryPackagePrefix);
      workspacePathToSourceRoot.put(workspacePath, candidateRoot);
    }

    // Add content entry base if it doesn't exist
    if (!workspacePathToSourceRoot.containsKey(directoryRoot)) {
      SourceRoot candidateRoot =
          new SourceRoot(directoryRoot, PackagePrefixCalculator.packagePrefixOf(directoryRoot));
      workspacePathToSourceRoot.put(directoryRoot, candidateRoot);
    }

    // First, create a graph of the directory structure from root to each source file
    Map<WorkspacePath, SourceRootDirectoryNode> sourceRootDirectoryNodeMap = Maps.newHashMap();
    SourceRootDirectoryNode rootNode = new SourceRootDirectoryNode(directoryRoot, null);
    sourceRootDirectoryNodeMap.put(directoryRoot, rootNode);
    for (SourceRoot sourceRoot : workspacePathToSourceRoot.values()) {
      final String sourcePathRelativeToDirectoryRoot =
          sourcePathRelativeToDirectoryRoot(directoryRoot, sourceRoot.workspacePath);
      List<String> pathComponents =
          !Strings.isNullOrEmpty(sourcePathRelativeToDirectoryRoot)
              ? PATH_SPLITTER.splitToList(sourcePathRelativeToDirectoryRoot)
              : ImmutableList.of();
      SourceRootDirectoryNode previousNode = rootNode;
      for (int i = 0; i < pathComponents.size(); ++i) {
        final WorkspacePath workspacePath =
            getWorkspacePathFromPathComponents(directoryRoot, pathComponents, i + 1);
        SourceRootDirectoryNode node = sourceRootDirectoryNodeMap.get(workspacePath);
        if (node == null) {
          node = new SourceRootDirectoryNode(workspacePath, pathComponents.get(i));
          sourceRootDirectoryNodeMap.put(workspacePath, node);
          previousNode.children.add(node);
        }
        previousNode = node;
      }
    }

    // Add package prefix votes at each directory node
    for (SourceRoot sourceRoot : workspacePathToSourceRoot.values()) {
      final String sourcePathRelativeToDirectoryRoot =
          sourcePathRelativeToDirectoryRoot(directoryRoot, sourceRoot.workspacePath);

      List<String> packageComponents = PACKAGE_SPLITTER.splitToList(sourceRoot.packagePrefix);
      List<String> pathComponents =
          !Strings.isNullOrEmpty(sourcePathRelativeToDirectoryRoot)
              ? PATH_SPLITTER.splitToList(sourcePathRelativeToDirectoryRoot)
              : ImmutableList.of();
      int packageIndex = packageComponents.size();
      int pathIndex = pathComponents.size();
      while (pathIndex >= 0 && packageIndex >= 0) {
        final WorkspacePath workspacePath =
            getWorkspacePathFromPathComponents(directoryRoot, pathComponents, pathIndex);

        SourceRootDirectoryNode node = sourceRootDirectoryNodeMap.get(workspacePath);

        String packagePrefix = PACKAGE_JOINER.join(packageComponents.subList(0, packageIndex));

        // If this is the source root containing Java files, we *have* to pick its package prefix
        // Otherwise just add a vote
        if (sourceRoot.workspacePath.equals(workspacePath)) {
          node.forcedPackagePrefix = packagePrefix;
        } else {
          node.packagePrefixVotes.add(packagePrefix);
        }

        String pathComponent = pathIndex > 0 ? pathComponents.get(pathIndex - 1) : "";
        String packageComponent = packageIndex > 0 ? packageComponents.get(packageIndex - 1) : "";
        if (!pathComponent.equals(packageComponent)) {
          break;
        }

        --packageIndex;
        --pathIndex;
      }
    }

    Map<WorkspacePath, SourceRoot> sourceRoots = Maps.newHashMap();
    SourceRootDirectoryNode root = sourceRootDirectoryNodeMap.get(directoryRoot);
    visitDirectoryNode(sourceRoots, root, null);

    for (SourceRoot sourceRoot : sourceRoots.values()) {
      result.add(
          BlazeSourceDirectory.builder(workspaceRoot.fileForPath(sourceRoot.workspacePath))
              .setPackagePrefix(sourceRoot.packagePrefix)
              .setGenerated(false)
              .build());
    }
  }

  private static String sourcePathRelativeToDirectoryRoot(
      WorkspacePath directoryRoot, WorkspacePath workspacePath) {
    int directoryRootLength = directoryRoot.relativePath().length();
    String relativePath = workspacePath.relativePath();
    final String relativeSourcePath;
    if (relativePath.length() > directoryRootLength) {
      if (directoryRootLength > 0) {
        relativeSourcePath = relativePath.substring(directoryRootLength + 1);
      } else {
        relativeSourcePath = relativePath;
      }
    } else {
      relativeSourcePath = "";
    }
    return relativeSourcePath;
  }

  private static WorkspacePath getWorkspacePathFromPathComponents(
      WorkspacePath directoryRoot, List<String> pathComponents, int pathIndex) {
    String directoryRootRelativePath = PATH_JOINER.join(pathComponents.subList(0, pathIndex));
    final WorkspacePath workspacePath;
    if (directoryRootRelativePath.isEmpty()) {
      workspacePath = directoryRoot;
    } else if (directoryRoot.isWorkspaceRoot()) {
      workspacePath = new WorkspacePath(directoryRootRelativePath);
    } else {
      workspacePath =
          new WorkspacePath(
              PATH_JOINER.join(directoryRoot.relativePath(), directoryRootRelativePath));
    }
    return workspacePath;
  }

  private static void visitDirectoryNode(
      Map<WorkspacePath, SourceRoot> sourceRoots,
      SourceRootDirectoryNode node,
      @Nullable String parentCompatiblePackagePrefix) {
    String packagePrefix =
        node.forcedPackagePrefix != null
            ? node.forcedPackagePrefix
            : pickMostFrequentlyOccurring(
                node.packagePrefixVotes,
                PackagePrefixCalculator.packagePrefixOf(node.workspacePath));
    packagePrefix = packagePrefix != null ? packagePrefix : parentCompatiblePackagePrefix;
    if (packagePrefix != null && !packagePrefix.equals(parentCompatiblePackagePrefix)) {
      sourceRoots.put(node.workspacePath, new SourceRoot(node.workspacePath, packagePrefix));
    }
    for (SourceRootDirectoryNode child : node.children) {
      String compatiblePackagePrefix = null;
      if (packagePrefix != null) {
        compatiblePackagePrefix =
            Strings.isNullOrEmpty(packagePrefix)
                ? child.directoryName
                : packagePrefix + "." + child.directoryName;
      }
      visitDirectoryNode(sourceRoots, child, compatiblePackagePrefix);
    }
  }

  @Nullable
  private static <T> T pickMostFrequentlyOccurring(Multiset<T> set, String prefer) {
    T best = null;
    int bestCount = 0;

    for (T candidate : set.elementSet()) {
      int candidateCount = set.count(candidate);
      if (candidateCount > bestCount || (candidateCount == bestCount && candidate.equals(prefer))) {
        best = candidate;
        bestCount = candidateCount;
      }
    }
    return best;
  }

  @Nullable
  private SourceRoot sourceRootForJavaSource(
      BlazeContext context,
      ArtifactLocationDecoder artifactLocationDecoder,
      SourceArtifact sourceArtifact,
      Collection<JavaPackageReader> javaPackageReaders) {

    String declaredPackage = null;
    for (JavaPackageReader reader : javaPackageReaders) {
      declaredPackage =
          reader.getDeclaredPackageOfJavaFile(context, artifactLocationDecoder, sourceArtifact);
      if (declaredPackage != null) {
        break;
      }
    }
    if (declaredPackage == null) {
      IssueOutput.warn(
              "Failed to inspect the package name of java source file: "
                  + sourceArtifact.artifactLocation)
          .inFile(artifactLocationDecoder.decode(sourceArtifact.artifactLocation))
          .submit(context);
      return null;
    }
    String parentPath = new File(sourceArtifact.artifactLocation.relativePath).getParent();
    return new SourceRoot(new WorkspacePath(Strings.nullToEmpty(parentPath)), declaredPackage);
  }

  static class SourceRoot {
    final WorkspacePath workspacePath;
    final String packagePrefix;

    public SourceRoot(WorkspacePath workspacePath, String packagePrefix) {
      this.workspacePath = workspacePath;
      this.packagePrefix = packagePrefix;
    }

    @Override
    public boolean equals(Object o) {
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      SourceRoot that = (SourceRoot) o;
      return Objects.equal(workspacePath, that.workspacePath)
          && Objects.equal(packagePrefix, that.packagePrefix);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(workspacePath, packagePrefix);
    }

    @Override
    public String toString() {
      return "SourceRoot {"
          + '\n'
          + "  workspacePath: "
          + workspacePath
          + '\n'
          + "  packagePrefix: "
          + packagePrefix
          + '\n'
          + '}';
    }
  }

  static class SourceRootDirectoryNode {
    final WorkspacePath workspacePath;
    @Nullable final String directoryName;
    final Set<SourceRootDirectoryNode> children = Sets.newHashSet();
    final Multiset<String> packagePrefixVotes = HashMultiset.create();
    String forcedPackagePrefix;

    public SourceRootDirectoryNode(WorkspacePath workspacePath, @Nullable String directoryName) {
      this.workspacePath = workspacePath;
      this.directoryName = directoryName;
    }
  }
}
