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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.hash.HashCode;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ClasspathTraversalTest {
  @Rule
  public TemporaryFolder tempDir = new TemporaryFolder();

  private static Collection<FileLike> traverse(Collection<File> files) throws IOException {
    Collection<Path> paths = FluentIterable.from(files)
        .transform(new Function<File, Path>() {
      @Override
      public Path apply(File file) {
        return file.toPath();
      }
    }).toList();
    final ImmutableList.Builder<FileLike> completeList = ImmutableList.builder();
    ClasspathTraverser traverser = new DefaultClasspathTraverser();
    traverser.traverse(new ClasspathTraversal(paths) {
      @Override
      public void visit(FileLike fileLike) {
        completeList.add(fileLike);
      }
    });
    return completeList.build();
  }

  private static void verifyFileLike(int expectedFiles, File... paths) throws IOException {
    int fileLikeCount = 0;
    for (FileLike fileLike : traverse(Lists.newArrayList(paths))) {
      String contents = CharStreams.toString(
          CharStreams.newReaderSupplier(new FileLikeInputSupplier(fileLike),
              Charsets.UTF_8));
      assertEquals("Relative file-like path mismatch", contents, fileLike.getRelativePath());
      fileLikeCount++;
    }
    assertEquals(expectedFiles, fileLikeCount);
  }

  @Test
  public void testDirectoryAndFile() throws IOException {
    File notADirectory = tempDir.newFile("not_a_directory.txt");
    Files.write("not_a_directory.txt", notADirectory, Charsets.UTF_8);
    File yesADir = tempDir.newFolder("is_a_directory");
    Files.write("foo.txt", new File(yesADir, "foo.txt"), Charsets.UTF_8);
    Files.write("bar.txt", new File(yesADir, "bar.txt"), Charsets.UTF_8);
    File aSubDir = new File(yesADir, "fizzbuzz");
    assertTrue("Failed to create dir: " + aSubDir, aSubDir.mkdir());
    Files.write("fizzbuzz/whatever.txt", new File(aSubDir, "whatever.txt"),
        Charsets.UTF_8);
    verifyFileLike(4, notADirectory, yesADir);
  }

  @Test
  public void testZip() throws IOException {
    String[] files = { "test/foo.txt", "bar.txt", "test/baz.txt" };
    File file = tempDir.newFile("test.zip");
    ZipOutputStream zipOut = new ZipOutputStream(
        new BufferedOutputStream(new FileOutputStream(file)));
    try {
      for (String filename : files) {
        ZipEntry entry = new ZipEntry(filename);
        zipOut.putNextEntry(entry);
        zipOut.write(filename.getBytes(Charsets.UTF_8));
      }
    } finally {
      zipOut.close();
    }
    verifyFileLike(3, file);
  }

  private static long getChecksum(Checksum algorithm, String data, Charset charset) {
    byte[] dataBytes = data.getBytes(charset);
    algorithm.update(dataBytes, 0, dataBytes.length);
    return algorithm.getValue();
  }

  @Test
  public void testZipHashing() throws IOException {
    String contents = "test crc32";
    final long contentsCrc32 = getChecksum(new CRC32(), contents, Charsets.UTF_8);
    File file = tempDir.newFile("test.zip");
    ZipOutputStream zipOut = new ZipOutputStream(
        new BufferedOutputStream(new FileOutputStream(file)));
    try {
      ZipEntry entry = new ZipEntry("foo.txt");
      zipOut.putNextEntry(entry);
      zipOut.write(contents.getBytes(Charsets.UTF_8));
    } finally {
      zipOut.close();
    }

    Collection<FileLike> entries = traverse(Collections.singleton(file));
    assertEquals(1, entries.size());
    FileLike entry = Iterables.getFirst(entries, null);
    assertEquals("CRC of input text should equal FileLike#fastHash",
        HashCode.fromLong(contentsCrc32), entry.fastHash());
  }
}
