// Copyright 2017 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.java.turbine.javac;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.io.ByteStreams;
import com.google.devtools.build.buildjar.jarhelper.JarCreator;
import com.google.devtools.build.java.turbine.javac.JavacTurbine.Result;
import com.google.turbine.options.TurbineOptions;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;

public abstract class AbstractJavacTurbineCompilationTest {

  @Rule public final TemporaryFolder temp = new TemporaryFolder();

  Path sourcedir;
  List<Path> sources;
  Path tempdir;
  Path output;
  Path outputDeps;

  final TurbineOptions.Builder optionsBuilder = TurbineOptions.builder();

  @Before
  public void setUp() throws IOException {
    sourcedir = temp.newFolder().toPath();
    tempdir = temp.newFolder("_temp").toPath();
    output = temp.newFile("out.jar").toPath();
    outputDeps = temp.newFile("out.jdeps").toPath();

    sources = new ArrayList<>();

    optionsBuilder
        .setOutput(output.toString())
        .setTempDir(tempdir.toString())
        .setOutputDeps(outputDeps.toString())
        .addAllJavacOpts(Arrays.asList("-source", "8", "-target", "8"))
        .setTargetLabel("//test");
  }

  protected void addSourceLines(String path, String... lines) throws IOException {
    Path source = sourcedir.resolve(path);
    sources.add(source);
    Files.write(source, Arrays.asList(lines), UTF_8);
  }

  protected void compile() throws IOException {
    optionsBuilder.addSources(sources.stream().map(p -> p.toString()).collect(toImmutableList()));
    try (JavacTurbine turbine =
        new JavacTurbine(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
            optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.OK_WITH_REDUCED_CLASSPATH);
    }
  }

  protected Map<String, byte[]> collectOutputs() throws IOException {
    return collectFiles(output);
  }

  static Map<String, byte[]> collectFiles(Path jar) throws IOException {
    Map<String, byte[]> files = new LinkedHashMap<>();
    try (JarFile jf = new JarFile(jar.toFile())) {
      Enumeration<JarEntry> entries = jf.entries();
      while (entries.hasMoreElements()) {
        JarEntry entry = entries.nextElement();
        files.put(entry.getName(), ByteStreams.toByteArray(jf.getInputStream(entry)));
      }
    }
    return files;
  }

  static String textify(byte[] bytes) {
    StringWriter sw = new StringWriter();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(sw, true)), 0);
    return sw.toString();
  }

  protected Path createClassJar(String jarName, Class<?>... classes) throws IOException {
    Path jarPath = temp.newFile(jarName).toPath();
    Manifest manifest = new Manifest();
    manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
    manifest.getMainAttributes().put(JarCreator.TARGET_LABEL, "//" + jarName);
    try (OutputStream os = Files.newOutputStream(jarPath);
        JarOutputStream jos = new JarOutputStream(os, manifest)) {
      for (Class<?> clazz : classes) {
        String classFileName = clazz.getName().replace('.', '/') + ".class";
        jos.putNextEntry(new JarEntry(classFileName));
        try (InputStream is = getClass().getClassLoader().getResourceAsStream(classFileName)) {
          ByteStreams.copy(is, jos);
        }
      }
    }
    return jarPath;
  }
}
