// Copyright (c) 2018, 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;

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static org.hamcrest.CoreMatchers.containsString;

import com.android.tools.r8.KotlinCompilerTool.KotlinCompiler;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.hamcrest.Matcher;

public abstract class KotlinTestBase extends TestBase {

  protected static final String checkParameterIsNotNullSignature =
      "void kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull("
          + "java.lang.Object, java.lang.String)";
  protected static final String throwParameterIsNotNullExceptionSignature =
      "void kotlin.jvm.internal.Intrinsics.throwParameterIsNullException(java.lang.String)";
  public static final String METADATA_DESCRIPTOR = "Lkotlin/Metadata;";
  public static final String METADATA_TYPE =
      DescriptorUtils.descriptorToJavaType(METADATA_DESCRIPTOR);

  private static final String RSRC = "kotlinR8TestResources";

  private static final Map<String, KotlinCompileMemoizer> compileMemoizers = new HashMap<>();

  protected final KotlinCompiler kotlinc;
  protected final KotlinTargetVersion targetVersion;
  protected final KotlinTestParameters kotlinParameters;

  protected KotlinTestBase(KotlinTestParameters kotlinParameters) {
    this.targetVersion = kotlinParameters.getTargetVersion();
    this.kotlinc = kotlinParameters.getCompiler();
    this.kotlinParameters = kotlinParameters;
  }

  protected static List<Path> getKotlinFilesInTestPackage(Package pkg) throws IOException {
    String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName());
    return Files.walk(Paths.get(ToolHelper.TESTS_DIR, "java", folder))
        .filter(path -> path.toString().endsWith(".kt"))
        .collect(Collectors.toList());
  }

  protected static Path getKotlinFileInTestPackage(Package pkg, String fileName) {
    String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName());
    return getKotlinFileInTest(folder, fileName);
  }

  protected static Path getKotlinFileInTest(String folder, String fileName) {
    return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName + FileUtils.KT_EXTENSION);
  }

  public static Path getKotlinFileInResource(String folder, String fileName) {
    return Paths.get(ToolHelper.TESTS_DIR, RSRC, folder, fileName + FileUtils.KT_EXTENSION);
  }

  public static List<Path> getKotlinFilesInResource(String folder) {
    try {
      return Files.walk(Paths.get(ToolHelper.TESTS_DIR, RSRC, folder))
          .filter(path -> path.toString().endsWith(".kt") || path.toString().endsWith(".java"))
          .collect(Collectors.toList());
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  protected Path getJavaJarFile(String folder) {
    return Paths.get(ToolHelper.TESTS_BUILD_DIR, RSRC,
        targetVersion.getFolderName(), folder + ".java" + FileUtils.JAR_EXTENSION);
  }

  protected Path getMappingfile(String folder, String mappingFileName) {
    return Paths.get(ToolHelper.TESTS_DIR, RSRC, folder, mappingFileName);
  }

  protected static Matcher<String> expectedInfoMessagesFromKotlinStdLib() {
    return containsString("No VersionRequirement");
  }

  protected KotlinCompilerTool kotlinCompilerTool() {
    return KotlinCompilerTool.create(CfRuntime.getCheckedInJdk9(), temp, kotlinc, targetVersion);
  }

  public static KotlinCompileMemoizer getCompileMemoizer(Path... source) {
    return new KotlinCompileMemoizer(Arrays.asList(source));
  }

  public static KotlinCompileMemoizer getCompileMemoizer(Collection<Path> sources) {
    assert sources.size() > 0;
    return new KotlinCompileMemoizer(sources);
  }

  public static KotlinCompileMemoizer getCompileMemoizer(
      Collection<Path> sources, String sharedFolder) {
    return compileMemoizers.computeIfAbsent(
        sharedFolder, ignore -> new KotlinCompileMemoizer(sources));
  }

  public ThrowableConsumer<R8TestCompileResult> assertUnusedKeepRuleForKotlinMetadata(
      boolean condition) {
    return compileResult -> {
      if (!condition) {
        return;
      }
      compileResult
          .getDiagnosticMessages()
          .assertInfoThatMatches(
              diagnosticMessage(
                  containsString(
                      "Proguard configuration rule does not match anything: `-keep class"
                          + " kotlin.Metadata")));
    };
  }

  public static class KotlinCompileMemoizer {

    private final Collection<Path> sources;
    private Consumer<KotlinCompilerTool> kotlinCompilerToolConsumer = x -> {};
    private final Map<KotlinCompiler, Map<KotlinTargetVersion, Path>> compiledPaths =
        new IdentityHashMap<>();

    public KotlinCompileMemoizer(Collection<Path> sources) {
      this.sources = sources;
    }

    public KotlinCompileMemoizer configure(Consumer<KotlinCompilerTool> consumer) {
      this.kotlinCompilerToolConsumer = consumer;
      return this;
    }

    public Path getForConfiguration(KotlinTestParameters kotlinParameters) {
      return getForConfiguration(
          kotlinParameters.getCompiler(), kotlinParameters.getTargetVersion());
    }

    public Path getForConfiguration(KotlinCompiler compiler, KotlinTargetVersion targetVersion) {
      Map<KotlinTargetVersion, Path> kotlinTargetVersionPathMap = compiledPaths.get(compiler);
      if (kotlinTargetVersionPathMap == null) {
        kotlinTargetVersionPathMap = new IdentityHashMap<>();
        compiledPaths.put(compiler, kotlinTargetVersionPathMap);
      }
      return kotlinTargetVersionPathMap.computeIfAbsent(
          targetVersion,
          ignored -> {
            try {
              return kotlinc(compiler, targetVersion)
                  .addSourceFiles(sources)
                  .apply(kotlinCompilerToolConsumer)
                  .compile();
            } catch (IOException e) {
              throw new RuntimeException(e);
            }
          });
    }
  }
}
