// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.internal;

import static org.junit.Assert.assertTrue;

import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.analysis.ProtoApplicationStats;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public abstract class YouTubeCompilationTestBase extends CompilationTestBase {

  static final String DEPLOY_JAR = "YouTubeRelease_deploy.jar";
  static final String PG_MAP = "YouTubeRelease_proguard.map";
  static final String PG_CONF = "YouTubeRelease_proguard.config";
  static final String PG_PROTO_CONF = "YouTubeRelease_proto_safety.pgconf";
  static final String PG_MISSING_CLASSES_CONF = "YouTubeRelease_proguard_missing_classes.config";

  final String base;
  final AndroidApiLevel apiLevel;

  public YouTubeCompilationTestBase(int majorVersion, int minorVersion, AndroidApiLevel apiLevel) {
    this.base =
        "third_party/youtube/youtube.android_"
            + majorVersion
            + "."
            + String.format("%02d", minorVersion)
            + "/";
    this.apiLevel = apiLevel;
  }

  protected AndroidApiLevel getApiLevel() {
    return apiLevel;
  }

  protected Path getDesugaredLibraryConfiguration() {
    Path path = Paths.get(base, "desugar_jdk_libs/full_desugar_jdk_libs.json");
    assertTrue(path.toFile().exists());
    return path;
  }

  protected Path getDesugaredLibraryJDKLibs() {
    Path path = Paths.get(base, "desugar_jdk_libs/jdk_libs_to_desugar.jar");
    assertTrue(path.toFile().exists());
    return path;
  }

  protected Path getDesugaredLibraryJDKLibsConfiguration() {
    Path path = Paths.get(base, "desugar_jdk_libs/desugar_jdk_libs_configuration.jar");
    assertTrue(path.toFile().exists());
    return path;
  }

  protected List<Path> getDesugaredLibraryKeepRuleFiles() {
    ImmutableList<Path> keepRuleFiles =
        ImmutableList.of(
            Paths.get(base, "desugar_jdk_libs/base.pgcfg"),
            Paths.get(base, "desugar_jdk_libs/minify_desugar_jdk_libs.pgcfg"));
    assertTrue(keepRuleFiles.stream().allMatch(keepRuleFile -> keepRuleFile.toFile().exists()));
    return keepRuleFiles;
  }

  protected List<Path> getKeepRuleFiles() {
    ImmutableList.Builder<Path> builder = ImmutableList.builder();
    builder.add(Paths.get(base).resolve(PG_CONF));
    builder.add(Paths.get(ToolHelper.PROGUARD_SETTINGS_FOR_INTERNAL_APPS).resolve(PG_CONF));
    for (String name : new String[] {PG_PROTO_CONF, PG_MISSING_CLASSES_CONF}) {
      Path config = Paths.get(base).resolve(name);
      if (config.toFile().exists()) {
        builder.add(config);
      }
    }
    return builder.build();
  }

  protected Path getLibraryFile() {
    Path filtered =
        Paths.get(base).resolve("legacy_YouTubeRelease_combined_library_jars_filtered.jar");
    if (filtered.toFile().exists()) {
      return filtered;
    }
    Path unfiltered = Paths.get(base, "legacy_YouTubeRelease_combined_library_jars.jar");
    assertTrue(unfiltered.toFile().exists());
    return unfiltered;
  }

  Path getLibraryFileWithoutDesugaredLibrary() throws IOException {
    Path libraryFile = getLibraryFile();
    Path filteredLibraryFile =
        Paths.get(libraryFile.toString().replace(".jar", "desugared_lib_filtered.jar"));
    ArchiveConsumer consumer = new ArchiveConsumer(filteredLibraryFile);
    ZipUtils.iter(
        libraryFile,
        (entry, inputStream) -> {
          String entryString = entry.toString();
          if (entryString.endsWith(".class") && !entryString.startsWith("j$")) {
            byte[] bytes = ByteStreams.toByteArray(inputStream);
            consumer.accept(ByteDataView.of(bytes), TestBase.extractClassDescriptor(bytes), null);
          }
        });
    consumer.finished(null);
    return filteredLibraryFile;
  }

  protected List<Path> getMainDexRuleFiles() {
    return ImmutableList.of(
        Paths.get(base).resolve("mainDexClasses.rules"),
        Paths.get(base).resolve("main-dex-classes-release-optimized.pgcfg"),
        Paths.get(base).resolve("main_dex_YouTubeRelease_proguard.cfg"));
  }

  protected List<Path> getProgramFiles() throws IOException {
    List<Path> result = new ArrayList<>();
    for (Path keepRuleFile : getKeepRuleFiles()) {
      for (String line : FileUtils.readAllLines(keepRuleFile)) {
        if (line.startsWith("-injars")) {
          String fileName = line.substring("-injars ".length());
          result.add(Paths.get(base).resolve(fileName));
        }
      }
    }
    if (result.isEmpty()) {
      Path path = Paths.get(base).resolve(DEPLOY_JAR);
      assert path.toFile().exists();
      result.add(path);
    }
    return result;
  }

  Path getReleaseApk() {
    return Paths.get(base).resolve("YouTubeRelease.apk");
  }

  Path getReleaseProguardMap() {
    return Paths.get(base).resolve(PG_MAP);
  }

  void printProtoStats(R8TestCompileResult compileResult) throws Exception {
    if (ToolHelper.isLocalDevelopment()) {
      DexItemFactory dexItemFactory = new DexItemFactory();
      ProtoApplicationStats original =
          new ProtoApplicationStats(dexItemFactory, new CodeInspector(getProgramFiles()));
      ProtoApplicationStats actual =
          new ProtoApplicationStats(dexItemFactory, compileResult.inspector(), original);
      ProtoApplicationStats baseline =
          new ProtoApplicationStats(
              dexItemFactory, new CodeInspector(getReleaseApk(), getReleaseProguardMap()));
      System.out.println(actual.getStats(baseline));
    }
  }
}
