/*
 * Copyright 2020 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.android.desugar.langmodel;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import java.util.Arrays;
import java.util.Collection;
import org.objectweb.asm.Type;

/**
 * Represents the identifiable name of a Java class or interface with convenient conversions among
 * different names.
 */
@AutoValue
public abstract class ClassName implements TypeMappable<ClassName> {

  public static final String IN_PROCESS_LABEL = "__desugar__/";

  private static final String IMMUTABLE_LABEL_LABEL = "__final__/";

  private static final String TYPE_ADAPTER_PACKAGE_ROOT = "desugar/runtime/typeadapter/";

  public static final TypeMapper IN_PROCESS_LABEL_STRIPPER =
      new TypeMapper(className -> className.stripPackagePrefix(IN_PROCESS_LABEL));

  public static final TypeMapper IMMUTABLE_LABEL_STRIPPER =
      new TypeMapper(className -> className.stripPackagePrefix(IMMUTABLE_LABEL_LABEL));

  private static final String TYPE_ADAPTER_SUFFIX = "Adapter";

  private static final String TYPE_CONVERTER_SUFFIX = "Converter";

  /**
   * The primitive type as specified at
   * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-2.html#jvms-2.3
   */
  private static final ImmutableMap<String, Type> PRIMITIVES_TYPES =
      ImmutableMap.<String, Type>builder()
          .put("V", Type.VOID_TYPE)
          .put("Z", Type.BOOLEAN_TYPE)
          .put("C", Type.CHAR_TYPE)
          .put("B", Type.BYTE_TYPE)
          .put("S", Type.SHORT_TYPE)
          .put("I", Type.INT_TYPE)
          .put("F", Type.FLOAT_TYPE)
          .put("J", Type.LONG_TYPE)
          .put("D", Type.DOUBLE_TYPE)
          .build();
  /**
   * The primitive type as specified at
   * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-2.html#jvms-2.3
   */
  private static final ImmutableMap<ClassName, ClassName> PRIMITIVES_TO_BOXED_TYPES =
      ImmutableMap.<ClassName, ClassName>builder()
          .put(ClassName.create(Type.VOID_TYPE), ClassName.create("java/lang/Void"))
          .put(ClassName.create(Type.BOOLEAN_TYPE), ClassName.create("java/lang/Boolean"))
          .put(ClassName.create(Type.CHAR_TYPE), ClassName.create("java/lang/Character"))
          .put(ClassName.create(Type.BYTE_TYPE), ClassName.create("java/lang/Byte"))
          .put(ClassName.create(Type.SHORT_TYPE), ClassName.create("java/lang/Short"))
          .put(ClassName.create(Type.INT_TYPE), ClassName.create("java/lang/Integer"))
          .put(ClassName.create(Type.FLOAT_TYPE), ClassName.create("java/lang/Float"))
          .put(ClassName.create(Type.LONG_TYPE), ClassName.create("java/lang/Long"))
          .put(ClassName.create(Type.DOUBLE_TYPE), ClassName.create("java/lang/Double"))
          .build();

  private static final ImmutableBiMap<String, String> SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS =
      ImmutableBiMap.<String, String>builder().put("javadesugar/", "jd$/").build();
  public static final TypeMapper SHADOWED_TO_MIRRORED_TYPE_MAPPER =
      new TypeMapper(ClassName::shadowedToMirrored);
  public static final TypeMapper IMMUTABLE_LABEL_ATTACHER =
      new TypeMapper(ClassName::withCoreTypeImmutableLabel);

  public static ClassName create(String binaryName) {
    checkArgument(
        !binaryName.contains("."),
        "Expected a binary/internal class name ('/'-delimited) instead of a qualified name."
            + " Actual: (%s)",
        binaryName);
    return new AutoValue_ClassName(binaryName);
  }

  public static ClassName create(Class<?> clazz) {
    return create(Type.getType(clazz));
  }

  public static ClassName create(Type asmType) {
    return create(asmType.getInternalName());
  }

  public static ClassName fromClassFileName(String fileName) {
    checkArgument(
        fileName.endsWith(".class"), "Expected a class file (*.class). Actual: (%s).", fileName);
    return ClassName.create(fileName.substring(0, fileName.length() - ".class".length()));
  }

  private static void checkPackagePrefixFormat(String prefix) {
    checkArgument(
        prefix.isEmpty() || prefix.endsWith("/"),
        "Expected (%s) to be a package prefix of ending with '/'.",
        prefix);
    checkArgument(
        !prefix.contains("."),
        "Expected a '/'-delimited binary name instead of a '.'-delimited qualified name for %s",
        prefix);
  }

  /**
   * The textual binary name used to index the class name, as defined at,
   * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.2.1
   */
  public abstract String binaryName();

  public final Type toAsmObjectType() {
    return isPrimitive() ? PRIMITIVES_TYPES.get(binaryName()) : Type.getObjectType(binaryName());
  }

  public final ClassName toBoxedType() {
    checkState(isPrimitive(), "Expected a primitive type for type boxing, but got %s", this);
    return PRIMITIVES_TO_BOXED_TYPES.get(this);
  }

  public final boolean isPrimitive() {
    return PRIMITIVES_TYPES.containsKey(binaryName());
  }

  public final boolean isWideType() {
    return "D".equals(binaryName()) || "J".equals(binaryName());
  }

  public final boolean isBoxedType() {
    return PRIMITIVES_TO_BOXED_TYPES.containsValue(this);
  }

  public final String qualifiedName() {
    return binaryName().replace('/', '.');
  }

  public ClassName innerClass(String innerClassSimpleName) {
    return ClassName.create(binaryName() + '$' + innerClassSimpleName);
  }

  public final String getPackageName() {
    String binaryName = binaryName();
    int i = binaryName.lastIndexOf('/');
    return i < 0 ? "" : binaryName.substring(0, i + 1);
  }

  public final String simpleName() {
    String binaryName = binaryName();
    int i = binaryName.lastIndexOf('/');
    return i < 0 ? binaryName : binaryName.substring(i + 1);
  }

  public final ClassName withSimpleNameSuffix(String suffix) {
    return ClassName.create(binaryName() + suffix);
  }

  public final String classFilePathName() {
    return binaryName() + ".class";
  }

  public final boolean hasInProcessLabel() {
    return hasPackagePrefix(IN_PROCESS_LABEL);
  }

  public final boolean hasImmutableLabel() {
    return hasPackagePrefix(IMMUTABLE_LABEL_LABEL);
  }

  /**
   * Returns a new instance of {@code ClassName} that represents the owner class with adapter
   * methods for an Android SDK APIs.
   */
  public final ClassName typeAdapterOwner() {
    checkState(
        !hasInProcessLabel() && !hasImmutableLabel(),
        "Expected a label-free type: Actual(%s)",
        this);
    checkState(
        isInPackageEligibleForTypeAdapter(),
        "Expected an Android SDK type to have an adapter: Actual (%s)",
        this);
    return withSimpleNameSuffix(TYPE_ADAPTER_SUFFIX).withPackagePrefix(TYPE_ADAPTER_PACKAGE_ROOT);
  }

  /**
   * Returns a new instance of {@code ClassName} that represents the owner class with conversion
   * methods between JDK built-in types and desguar-mirrored types.
   */
  public final ClassName typeConverterOwner() {
    checkState(
        !hasInProcessLabel() && !hasImmutableLabel(),
        "Expected a label-free type: Actual(%s)",
        this);
    checkState(
        isDesugarShadowedType(),
        "Expected an JDK built-in type to have an converter: Actual (%s)",
        this);
    return withSimpleNameSuffix(TYPE_CONVERTER_SUFFIX).withPackagePrefix(TYPE_ADAPTER_PACKAGE_ROOT);
  }

  /**
   * Returns a new instance of {@code ClassName} attached with an immutable label which marks the
   * type is not subject to further desugar operations until the final label striping.
   */
  public final ClassName withCoreTypeImmutableLabel() {
    return isDesugarShadowedType() ? withPackagePrefix(IMMUTABLE_LABEL_LABEL) : this;
  }

  /**
   * Returns a new instance of {@code ClassName} that is the desugar-mirrored core type (e.g. {@code
   * j$/time/MonthDay}) of the current shadowed built-in core type, assuming {@code this} instance
   * is a desugared-shadowed built-in core type.
   */
  public final ClassName shadowedToMirrored() {
    return SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS.keySet().stream()
        .filter(this::hasPackagePrefix)
        .map(
            prefix ->
                replacePackagePrefix(prefix, SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS.get(prefix)))
        .findAny()
        .orElse(this);
  }

  /**
   * Returns a new instance of {@code ClassName} that is a shadowed built-in core type (e.g. {@code
   * java/time/MonthDay}) of the current desugar-mirrored core type, assuming {@code this} instance
   * is a desugar-mirrored core type.
   */
  public final ClassName mirroredToShadowed() {
    ImmutableBiMap<String, String> verbatimTypeMappings =
        SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS.inverse();
    return verbatimTypeMappings.keySet().stream()
        .filter(this::hasPackagePrefix)
        .map(prefix -> replacePackagePrefix(prefix, verbatimTypeMappings.get(prefix)))
        .findAny()
        .orElse(this);
  }

  public final ClassName withPackagePrefix(String prefix) {
    checkPackagePrefixFormat(prefix);
    return ClassName.create(prefix + binaryName());
  }

  public final boolean hasPackagePrefix(String prefix) {
    return binaryName().startsWith(prefix);
  }

  public final boolean hasAnyPackagePrefix(String... prefixes) {
    return Arrays.stream(prefixes).anyMatch(this::hasPackagePrefix);
  }

  public final boolean hasAnyPackagePrefix(Collection<String> prefixes) {
    return prefixes.stream().anyMatch(this::hasPackagePrefix);
  }

  public final boolean isDesugarEligible(boolean enableDesugarBuiltinJdk) {
    if (isDesugarShadowedType()) {
      return enableDesugarBuiltinJdk;
    }
    return !isInPackageEligibleForTypeAdapter()
        && !isInDesugarRuntimeLibrary()
        && !isDesugarMirroredType();
  }

  public final boolean isInPackageEligibleForTypeAdapter() {
    // TODO(b/152573900): Update to hasPackagePrefix("android/") once all package-wise incremental
    // rollouts are complete.
    return hasAnyPackagePrefix("android/testing/");
  }

  public final boolean isInDesugarRuntimeLibrary() {
    return hasAnyPackagePrefix(
        "com/google/devtools/build/android/desugar/runtime/", "desugar/runtime/");
  }

  public final boolean isDesugarShadowedType() {
    return hasAnyPackagePrefix(SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS.keySet());
  }

  public final boolean isDesugarMirroredType() {
    return hasAnyPackagePrefix(SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS.values());
  }

  private ClassName stripPackagePrefix(String prefix) {
    return hasPackagePrefix(prefix) ? stripRequiredPackagePrefix(prefix) : this;
  }

  private ClassName stripRequiredPackagePrefix(String prefix) {
    return replacePackagePrefix(/* originalPrefix= */ prefix, /* targetPrefix= */ "");
  }

  private ClassName replacePackagePrefix(String originalPrefix, String targetPrefix) {
    checkState(
        hasPackagePrefix(originalPrefix),
        "Expected %s to have a package prefix of (%s) before stripping.",
        this,
        originalPrefix);
    checkPackagePrefixFormat(targetPrefix);
    return ClassName.create(targetPrefix + binaryName().substring(originalPrefix.length()));
  }

  @Override
  public ClassName acceptTypeMapper(TypeMapper typeMapper) {
    return typeMapper.map(this);
  }
}
