package com.android.tools.r8.ir.desugar;

import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.NestMemberClassAttribute;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.origin.SynthesizedOrigin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public abstract class NestBasedAccessDesugaring {

  // Short names to avoid creating long strings
  private static final String NEST_ACCESS_NAME_PREFIX = "-$$Nest$";
  private static final String NEST_ACCESS_METHOD_NAME_PREFIX = NEST_ACCESS_NAME_PREFIX + "m";
  private static final String NEST_ACCESS_STATIC_METHOD_NAME_PREFIX =
      NEST_ACCESS_NAME_PREFIX + "sm";
  private static final String NEST_ACCESS_FIELD_GET_NAME_PREFIX = NEST_ACCESS_NAME_PREFIX + "fget";
  private static final String NEST_ACCESS_STATIC_GET_FIELD_NAME_PREFIX =
      NEST_ACCESS_NAME_PREFIX + "sfget";
  private static final String NEST_ACCESS_FIELD_PUT_NAME_PREFIX = NEST_ACCESS_NAME_PREFIX + "fput";
  private static final String NEST_ACCESS_STATIC_PUT_FIELD_NAME_PREFIX =
      NEST_ACCESS_NAME_PREFIX + "sfput";
  public static final String NEST_CONSTRUCTOR_NAME = NEST_ACCESS_NAME_PREFIX + "Constructor";
  private static final String FULL_NEST_CONTRUCTOR_NAME = "L" + NEST_CONSTRUCTOR_NAME + ";";

  protected final AppView<?> appView;
  private final HashMap<DexEncodedMethod, DexEncodedMethod> bridges = new HashMap<>();
  private final HashMap<DexFieldWithAccess, DexEncodedMethod> fieldBridges = new HashMap<>();
  private final HashMap<DexEncodedMethod, DexProgramClass> deferredBridgesToAdd = new HashMap<>();
  private DexProgramClass nestConstructor;

  public NestBasedAccessDesugaring(AppView<?> appView) {
    this.appView = appView;
  }

  public void analyzeNests() {
    // TODO(b/130529338) we don't need to compute a list with all live nests.
    // we just need to iterate all live nests.
    List<List<DexType>> liveNests = computeLiveNests();
    processLiveNests(liveNests);
    addDeferredBridges();
  }

  public void synthetizeNestConstructor(DexApplication.Builder<?> builder) {
    if (nestConstructor != null) {
      appView.appInfo().addSynthesizedClass(nestConstructor);
      builder.addSynthesizedClass(nestConstructor, true);
    }
  }

  private void addDeferredBridges() {
    for (Map.Entry<DexEncodedMethod, DexProgramClass> entry : deferredBridgesToAdd.entrySet()) {
      entry.getValue().addMethod(entry.getKey());
    }
  }

  private void processLiveNests(List<List<DexType>> liveNests) {
    for (List<DexType> nest : liveNests) {
      for (DexType type : nest) {
        DexClass clazz = appView.definitionFor(type);
        if (clazz == null) {
          // TODO(b/130529338) We could throw only a warning if a class is missing.
          throw abortCompilationDueToIncompleteNest(nest);
        }
        NestBasedAccessDesugaringUseRegistry registry =
            new NestBasedAccessDesugaringUseRegistry(nest, clazz);
        for (DexEncodedMethod method : clazz.methods()) {
          method.registerCodeReferences(registry);
        }
      }
    }
  }

  private RuntimeException abortCompilationDueToIncompleteNest(List<DexType> nest) {
    List<String> programClassesFromNest = new ArrayList<>();
    List<String> unavailableClasses = new ArrayList<>();
    List<String> otherClasses = new ArrayList<>();
    for (DexType type : nest) {
      DexClass clazz = appView.definitionFor(type);
      if (clazz == null) {
        unavailableClasses.add(type.getName());
      } else if (clazz.isProgramClass()) {
        programClassesFromNest.add(type.getName());
      } else {
        assert clazz.isLibraryClass() || clazz.isClasspathClass();
        otherClasses.add(type.getName());
      }
    }
    StringBuilder stringBuilder =
        new StringBuilder("Classes ")
            .append(String.join(", ", programClassesFromNest))
            .append(" requires its nest mates ")
            .append(String.join(", ", unavailableClasses))
            .append(" to be on program or class path for compilation to succeed)");
    if (!otherClasses.isEmpty()) {
      stringBuilder
          .append("(Classes ")
          .append(String.join(", ", otherClasses))
          .append(" from the same nest were available).");
    }
    throw new CompilationError(stringBuilder.toString());
  }

  private List<List<DexType>> computeLiveNests() {
    List<List<DexType>> liveNests = new ArrayList<>();
    // It is possible that a nest member is on the program path but its nest host
    // is only in the class path. Nests are therefore computed the first time a
    // nest member is met, host or not. The computedNestHosts list is there to
    // avoid processing multiple times the same nest.
    Set<DexType> computedNestHosts = new HashSet<>();
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      if (clazz.isInANest()) {
        DexType hostType =
            clazz.isNestHost() ? clazz.type : clazz.getNestHostClassAttribute().getNestHost();
        if (!computedNestHosts.contains(hostType)) {
          computedNestHosts.add(hostType);
          DexClass host =
              clazz.isNestHost()
                  ? clazz
                  : appView.definitionFor(clazz.getNestHostClassAttribute().getNestHost());
          if (host == null) {
            throw abortCompilationDueToMissingNestHost(clazz);
          }
          List<DexType> classesInNest = new ArrayList<>();
          for (NestMemberClassAttribute nestmate : host.getNestMembersClassAttributes()) {
            classesInNest.add(nestmate.getNestMember());
          }
          classesInNest.add(host.type);
          liveNests.add(classesInNest);
        }
      }
    }
    return liveNests;
  }

  private RuntimeException abortCompilationDueToMissingNestHost(DexProgramClass compiledClass) {
    String nestHostName = compiledClass.getNestHostClassAttribute().getNestHost().getName();
    throw new CompilationError(
        "Class "
            + compiledClass.type.getName()
            + " requires its nest host "
            + nestHostName
            + " to be on program or class path for compilation to succeed.");
  }

  protected abstract void shouldRewriteCalls(DexMethod method, DexMethod bridge);

  protected abstract void shouldRewriteInitializers(DexMethod method, DexMethod bridge);

  protected abstract void shouldRewriteStaticGetFields(DexField field, DexMethod bridge);

  protected abstract void shouldRewriteStaticPutFields(DexField field, DexMethod bridge);

  protected abstract void shouldRewriteInstanceGetFields(DexField field, DexMethod bridge);

  protected abstract void shouldRewriteInstancePutFields(DexField field, DexMethod bridge);

  private RuntimeException abortCompilationDueToBridgeRequiredOnLibraryClass(
      DexClass compiledClass, DexClass libraryClass) {
    throw new CompilationError(
        "Class "
            + compiledClass.type.getName()
            + " requires the insertion of a bridge on the library class "
            + libraryClass.type.getName()
            + " which is impossible.");
  }

  private DexString methodBridgeName(DexEncodedMethod method) {
    String methodName = method.method.name.toString();
    String fullName;
    if (method.isStatic()) {
      fullName = NEST_ACCESS_STATIC_METHOD_NAME_PREFIX + methodName;
    } else {
      fullName = NEST_ACCESS_METHOD_NAME_PREFIX + methodName;
    }
    return appView.dexItemFactory().createString(fullName);
  }

  private DexString fieldBridgeName(DexFieldWithAccess access) {
    String fieldName = access.field.field.name.toString();
    String fullName;
    if (access.isInstanceGet()) {
      fullName = NEST_ACCESS_FIELD_GET_NAME_PREFIX + fieldName;
    } else if (access.isStaticGet()) {
      fullName = NEST_ACCESS_STATIC_GET_FIELD_NAME_PREFIX + fieldName;
    } else if (access.isInstancePut()) {
      fullName = NEST_ACCESS_FIELD_PUT_NAME_PREFIX + fieldName;
    } else {
      assert access.isStaticPut();
      fullName = NEST_ACCESS_STATIC_PUT_FIELD_NAME_PREFIX + fieldName;
    }
    return appView.dexItemFactory().createString(fullName);
  }

  private DexProgramClass ensureNestConstructorClass() {
    if (nestConstructor != null) {
      return nestConstructor;
    }
    nestConstructor =
        new DexProgramClass(
            appView.dexItemFactory().createType(FULL_NEST_CONTRUCTOR_NAME),
            null,
            new SynthesizedOrigin("Nest based access desugaring", getClass()),
            // Make the synthesized class public since shared in the whole program.
            ClassAccessFlags.fromDexAccessFlags(
                Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
            appView.dexItemFactory().objectType,
            DexTypeList.empty(),
            appView.dexItemFactory().createString("nest"),
            null,
            Collections.emptyList(),
            null,
            Collections.emptyList(),
            DexAnnotationSet.empty(),
            DexEncodedField.EMPTY_ARRAY,
            DexEncodedField.EMPTY_ARRAY,
            DexEncodedMethod.EMPTY_ARRAY,
            DexEncodedMethod.EMPTY_ARRAY,
            appView.dexItemFactory().getSkipNameValidationForTesting());
    return nestConstructor;
  }

  private class NestBasedAccessDesugaringUseRegistry extends UseRegistry {

    private final List<DexType> nest;
    private final DexClass currentClass;

    NestBasedAccessDesugaringUseRegistry(List<DexType> nest, DexClass currentClass) {
      super(appView.options().itemFactory);
      this.nest = nest;
      this.currentClass = currentClass;
    }

    private boolean registerInvoke(DexMethod method) {
      if (method.holder == currentClass.type || !nest.contains(method.holder)) {
        return false;
      }
      DexEncodedMethod target = appView.definitionFor(method);
      if (target == null || !target.accessFlags.isPrivate()) {
        return false;
      }
      DexEncodedMethod bridge =
          bridges.computeIfAbsent(
              target,
              k -> {
                DexClass holder = appView.definitionFor(method.holder);
                DexEncodedMethod localBridge =
                    target.isInstanceInitializer()
                        ? target.toInitializerForwardingBridge(
                            holder, appView, ensureNestConstructorClass())
                        : target.toStaticForwardingBridge(
                            holder, appView, methodBridgeName(target));
                // Accesses to program classes private members require bridge insertion.
                if (holder.isProgramClass()) {
                  deferredBridgesToAdd.put(localBridge, holder.asProgramClass());
                } else if (holder.isLibraryClass()) {
                  throw abortCompilationDueToBridgeRequiredOnLibraryClass(currentClass, holder);
                }
                return localBridge;
              });
      // In program classes, any access to nest mate private member needs to be rewritten.
      if (currentClass.isProgramClass()) {
        if (target.isInstanceInitializer()) {
          shouldRewriteInitializers(method, bridge.method);
        } else {
          shouldRewriteCalls(method, bridge.method);
        }
      }
      return true;
    }

    private boolean registerFieldAccess(DexField field, boolean isGet) {
      if (field.holder == currentClass.type || !nest.contains(field.holder)) {
        return false;
      }
      DexEncodedField target = appView.definitionFor(field);
      if (target == null || !target.accessFlags.isPrivate()) {
        return false;
      }
      DexFieldWithAccess key = new DexFieldWithAccess(target, isGet);
      DexEncodedMethod bridge =
          fieldBridges.computeIfAbsent(
              key,
              k -> {
                DexClass holder = appView.definitionFor(field.holder);
                DexEncodedMethod localBridge =
                    DexEncodedMethod.createFieldAccessorBridge(
                        key, holder, appView, fieldBridgeName(key));
                // Accesses to program classes private members require bridge insertion.
                if (holder.isProgramClass()) {
                  deferredBridgesToAdd.put(localBridge, holder.asProgramClass());
                } else if (holder.isLibraryClass()) {
                  throw abortCompilationDueToBridgeRequiredOnLibraryClass(currentClass, holder);
                }
                return localBridge;
              });
      // In program classes, any access to nest mate private member needs to be rewritten.
      if (currentClass.isProgramClass()) {
        if (isGet) {
          if (target.isStatic()) {
            shouldRewriteStaticGetFields(field, bridge.method);
          } else {
            shouldRewriteInstanceGetFields(field, bridge.method);
          }
        } else {
          if (target.isStatic()) {
            shouldRewriteStaticPutFields(field, bridge.method);
          } else {
            shouldRewriteInstancePutFields(field, bridge.method);
          }
        }
      }
      return true;
    }

    @Override
    public boolean registerInvokeVirtual(DexMethod method) {
      // Calls to class nest mate private methods are targeted by invokeVirtual in jdk11.
      // The spec recommends to do so, but do not enforce it, hence invokeDirect is also registered.
      return registerInvoke(method);
    }

    @Override
    public boolean registerInvokeDirect(DexMethod method) {
      return registerInvoke(method);
    }

    @Override
    public boolean registerInvokeStatic(DexMethod method) {
      return registerInvoke(method);
    }

    @Override
    public boolean registerInvokeInterface(DexMethod method) {
      // Calls to interface nest mate private methods are targeted by invokeInterface in jdk11.
      // The spec recommends to do so, but do not enforce it, hence invokeDirect is also registered.
      return registerInvoke(method);
    }

    @Override
    public boolean registerInvokeSuper(DexMethod method) {
      // Cannot target private method.
      return false;
    }

    @Override
    public boolean registerInstanceFieldWrite(DexField field) {
      return registerFieldAccess(field, false);
    }

    @Override
    public boolean registerInstanceFieldRead(DexField field) {
      return registerFieldAccess(field, true);
    }

    @Override
    public boolean registerNewInstance(DexType type) {
      // Unrelated to access based control.
      // The <init> method has to be rewritten instead
      // and <init> is called through registerInvoke.
      return false;
    }

    @Override
    public boolean registerStaticFieldRead(DexField field) {
      return registerFieldAccess(field, true);
    }

    @Override
    public boolean registerStaticFieldWrite(DexField field) {
      return registerFieldAccess(field, false);
    }

    @Override
    public boolean registerTypeReference(DexType type) {
      // Unrelated to access based control.
      return false;
    }
  }

  public static final class DexFieldWithAccess {

    private final DexEncodedField field;
    private final boolean isGet;

    public DexFieldWithAccess(DexEncodedField field, boolean isGet) {
      this.field = field;
      this.isGet = isGet;
    }

    @Override
    public int hashCode() {
      return Objects.hash(field, isGet);
    }

    @Override
    public boolean equals(Object o) {
      if (o == null) {
        return false;
      }
      if (getClass() != o.getClass()) {
        return false;
      }
      DexFieldWithAccess other = (DexFieldWithAccess) o;
      return isGet == other.isGet && field == other.field;
    }

    public boolean isGet() {
      return isGet;
    }

    public boolean isStatic() {
      return field.accessFlags.isStatic();
    }

    public boolean isPut() {
      return !isGet();
    }

    public boolean isInstance() {
      return !isStatic();
    }

    public boolean isStaticGet() {
      return isStatic() && isGet();
    }

    public boolean isStaticPut() {
      return isStatic() && isPut();
    }

    public boolean isInstanceGet() {
      return isInstance() && isGet();
    }

    public boolean isInstancePut() {
      return isInstance() && isPut();
    }

    public DexType getType() {
      return field.field.type;
    }

    public DexType getHolder() {
      return field.field.holder;
    }

    public DexField getField() {
      return field.field;
    }

    public int bridgeParameterCount() {
      if (isGet() && isStatic()) {
        return 0;
      }
      if (isPut() && isInstance()) {
        return 2;
      }
      return 1;
    }
  }
}
