// Copyright (c) 2023, 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.utils;

import com.android.tools.r8.CompatProguardCommandBuilder;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

public class CompileDumpBase {

  static void setEnableExperimentalMissingLibraryApiModeling(
      Object builder, boolean enableMissingLibraryApiModeling) {
    getReflectiveBuilderMethod(
            builder, "setEnableExperimentalMissingLibraryApiModeling", boolean.class)
        .accept(new Object[] {enableMissingLibraryApiModeling});
  }

  static void setAndroidPlatformBuild(Object builder, boolean androidPlatformBuild) {
    getReflectiveBuilderMethod(builder, "setAndroidPlatformBuild", boolean.class)
        .accept(new Object[] {androidPlatformBuild});
  }

  static void addArtProfilesForRewriting(Object builder, Map<Path, Path> artProfileFiles) {
    try {
      Class<?> artProfileProviderClass =
          Class.forName("com.android.tools.r8.profile.art.ArtProfileProvider");
      Class<?> artProfileConsumerClass =
          Class.forName("com.android.tools.r8.profile.art.ArtProfileConsumer");
      artProfileFiles.forEach(
          (artProfile, residualArtProfile) ->
              getReflectiveBuilderMethod(
                      builder,
                      "addArtProfileForRewriting",
                      artProfileProviderClass,
                      artProfileConsumerClass)
                  .accept(
                      new Object[] {
                        createArtProfileProvider(artProfile),
                        createResidualArtProfileConsumer(residualArtProfile)
                      }));
    } catch (ClassNotFoundException e) {
      // Ignore.
    }
  }

  static void addStartupProfileProviders(Object builder, List<Path> startupProfileFiles) {
    getReflectiveBuilderMethod(builder, "addStartupProfileProviders", Collection.class)
        .accept(new Object[] {createStartupProfileProviders(startupProfileFiles)});
  }

  static Object createArtProfileProvider(Path artProfile) {
    Object[] artProfileProvider = new Object[1];
    boolean found =
        callReflectiveUtilsMethod(
            "createArtProfileProviderFromDumpFile",
            new Class<?>[] {Path.class},
            fn -> artProfileProvider[0] = fn.apply(new Object[] {artProfile}));
    if (!found) {
      System.out.println(
          "Unable to add art profiles as input. "
              + "Method createArtProfileProviderFromDumpFile() was not found.");
      return null;
    }
    System.out.println(artProfileProvider[0]);
    return artProfileProvider[0];
  }

  static Object createResidualArtProfileConsumer(Path residualArtProfile) {
    Object[] residualArtProfileConsumer = new Object[1];
    boolean found =
        callReflectiveUtilsMethod(
            "createResidualArtProfileConsumerFromDumpFile",
            new Class<?>[] {Path.class},
            fn -> residualArtProfileConsumer[0] = fn.apply(new Object[] {residualArtProfile}));
    if (!found) {
      System.out.println(
          "Unable to add art profiles as input. "
              + "Method createResidualArtProfileConsumerFromDumpFile() was not found.");
      return null;
    }
    System.out.println(residualArtProfileConsumer[0]);
    return residualArtProfileConsumer[0];
  }

  static Collection<Object> createStartupProfileProviders(List<Path> startupProfileFiles) {
    List<Object> startupProfileProviders = new ArrayList<>();
    for (Path startupProfileFile : startupProfileFiles) {
      boolean found =
          callReflectiveUtilsMethod(
              "createStartupProfileProviderFromDumpFile",
              new Class<?>[] {Path.class},
              fn -> startupProfileProviders.add(fn.apply(new Object[] {startupProfileFile})));
      if (!found) {
        System.out.println(
            "Unable to add startup profiles as input. "
                + "Method createStartupProfileProviderFromDumpFile() was not found.");
        break;
      }
    }
    return startupProfileProviders;
  }

  static Consumer<Object[]> getReflectiveBuilderMethod(
      Object builder, String setter, Class<?>... parameters) {
    try {
      Method declaredMethod = CompatProguardCommandBuilder.class.getMethod(setter, parameters);
      return args -> {
        try {
          declaredMethod.invoke(builder, args);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      };
    } catch (NoSuchMethodException e) {
      System.out.println(setter + " is not available on the compiledump version.");
      // The option is not available so we just return an empty consumer
      return args -> {};
    }
  }

  static boolean callReflectiveUtilsMethod(
      String methodName, Class<?>[] parameters, Consumer<Function<Object[], Object>> fnConsumer) {
    Class<?> utilsClass;
    try {
      utilsClass = Class.forName("com.android.tools.r8.utils.CompileDumpUtils");
    } catch (ClassNotFoundException e) {
      return false;
    }

    Method declaredMethod;
    try {
      declaredMethod = utilsClass.getDeclaredMethod(methodName, parameters);
    } catch (NoSuchMethodException e) {
      return false;
    }

    fnConsumer.accept(
        args -> {
          try {
            return declaredMethod.invoke(null, args);
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
        });
    return true;
  }

  // We cannot use StringResource since this class is added to the class path and has access only
  // to the public APIs.
  static String readAllBytesJava7(Path filePath) {
    String content = "";

    try {
      content = new String(Files.readAllBytes(filePath));
    } catch (IOException e) {
      e.printStackTrace();
    }

    return content;
  }
}
