// Copyright 2015 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.devtools.build.android;

import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hasher;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.logging.Logger;

/**
 * Deduplicates identical files in the provided directories. 
 * <p>
 * This is necessary for the andorid_resources deprecation -- the old style of inheritance
 * required all relevant resources to be copied from each dependency. This means each resource is
 * duplicated for each resource set. This modifier creates a sym link forest for each unique file
 * on a first come, first serve basis. Which makes aapt and the merging code loads happier.
 */
public class FileDeDuplicator implements DirectoryModifier {
  private static final Logger LOGGER = Logger.getLogger(FileDeDuplicator.class.getName());

  private static final class ConditionalCopyVisitor extends SimpleFileVisitor<Path> {
    private final Path newRoot;
    private final Path workingDir;
    private Multimap<Path, HashCode> seen;
    private HashFunction hashFunction;

    private ConditionalCopyVisitor(Path newRoot, Path workingDir,
        Multimap<Path, HashCode> seen, HashFunction hashFunction) {
      this.newRoot = newRoot;
      this.workingDir = workingDir;
      this.seen = seen;
      this.hashFunction = hashFunction;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        throws IOException {
      Files.createDirectories(newRoot.resolve(workingDir.relativize(dir)));
      return super.preVisitDirectory(dir, attrs);
    }
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      Path relativePath = workingDir.relativize(file);
      final HashCode fileHash = hashPath(file, hashFunction.newHasher());
      if (!seen.get(relativePath).contains(fileHash)) {
        seen.get(relativePath).add(fileHash);
        // TODO(bazel-team): Change to a symlink when the AOSP merge code supports symlinks.
        Files.copy(file, newRoot.resolve(relativePath));
        // Files.createSymbolicLink(newRoot.resolve(workingDir.relativize(file)), file);
      } else {
        LOGGER.warning(String.format("Duplicated file %s [%s]", relativePath, file));
      }
      return super.visitFile(file, attrs);
    }
  }

  private static HashCode hashPath(Path file, final Hasher hasher) throws IOException {
    byte[] tmpBuffer = new byte[512];
    final InputStream in = Files.newInputStream(file);
    for (int read = in.read(tmpBuffer); read > 0; read = in.read(tmpBuffer)) {
      hasher.putBytes(tmpBuffer, 0, read);
    }
    final HashCode fileHash = hasher.hash();
    in.close();
    return fileHash;
  }

  private final Multimap<Path, HashCode> seen;
  private final HashFunction hashFunction;
  private final Path out;
  private final Path workingDirectory;

  public FileDeDuplicator(HashFunction hashFunction, Path out, Path workingDirectory) {
    this.hashFunction = hashFunction;
    this.workingDirectory = workingDirectory;
    this.seen = HashMultimap.create();
    this.out = out;
  }

  private ImmutableList<Path> conditionallyCopy(ImmutableList<Path> roots)
      throws IOException {
    final Builder<Path> builder = ImmutableList.builder();
    for (Path root : roots) {
      Preconditions.checkArgument(root.startsWith(workingDirectory),
          root + " must start with root " + workingDirectory  + " from " + roots);
      Preconditions.checkArgument(!root.equals(workingDirectory),
          "Cannot deduplicate root directory: " + root + " from " + roots);
      if (!seen.containsKey(root)) {
        seen.put(root, null);
        final Path newRoot = out.resolve(workingDirectory.relativize(root));
        Files.walkFileTree(root, ImmutableSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
            new ConditionalCopyVisitor(newRoot, root, seen, hashFunction));
        builder.add(newRoot);
      } else {
        // Duplicated directories are ok -- multiple files from different libraries
        // can reside in the same directory, but duplicate files should not be seen mulitple times.
      }
    }
    return builder.build();
  }

  @Override
  public ImmutableList<Path> modify(ImmutableList<Path> directories) {
    try {
      return conditionallyCopy(directories);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}
