// Copyright (c) 2021, 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.ir.desugar.nest;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
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.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.D8MethodProcessor;
import com.android.tools.r8.profile.rewriting.ProfileRewritingNestBasedAccessDesugaringEventConsumer;
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

/**
 * Responsible for reporting desugar dependencies and for synthesizing bridges in the program for
 * accesses from the classpath into the program.
 */
public class D8NestBasedAccessDesugaring extends NestBasedAccessDesugaring {

  D8NestBasedAccessDesugaring(AppView<?> appView) {
    super(appView);
  }

  public void reportDesugarDependencies() {
    forEachNest(
        nest -> {
          if (nest.hasMissingMembers()) {
            throw appView.options().errorMissingNestMember(nest);
          }
          DexClass hostClass = nest.getHostClass();
          for (DexClass memberClass : nest.getMembers()) {
            if (hostClass.isProgramClass() || memberClass.isProgramClass()) {
              appView.appInfo().reportDependencyEdge(hostClass, memberClass);
              appView.appInfo().reportDependencyEdge(memberClass, hostClass);
            }
          }
        },
        classWithoutHost -> {
          throw appView.options().errorMissingNestHost(classWithoutHost);
        });
  }

  public static void checkAndFailOnIncompleteNests(AppView<?> appView) {
    forEachNest(
        nest -> {
          if (nest.hasMissingMembers()) {
            throw appView.options().errorMissingNestMember(nest);
          }
        },
        classWithoutHost -> {
          throw appView.options().errorMissingNestHost(classWithoutHost);
        },
        appView);
  }

  public void clearNestAttributes() {
    forEachNest(
        nest -> {
          nest.getHostClass().clearNestMembers();
          nest.getMembers().forEach(DexClass::clearNestHost);
        },
        classWithoutHost -> {
          // Do Nothing
        });
  }

  public void synthesizeBridgesForNestBasedAccessesOnClasspath(
      D8MethodProcessor methodProcessor, ExecutorService executorService)
      throws ExecutionException {
    List<DexClasspathClass> classpathClassesInNests = new ArrayList<>();
    forEachNest(
        nest -> {
          if (nest.getHostClass().isClasspathClass()) {
            classpathClassesInNests.add(nest.getHostClass().asClasspathClass());
          }
          Iterables.addAll(classpathClassesInNests, nest.getClasspathMembers());
        });

    NestBasedAccessDesugaringEventConsumer eventConsumer =
        ProfileRewritingNestBasedAccessDesugaringEventConsumer.attach(
            methodProcessor.getProfileCollectionAdditions(),
            new NestBasedAccessDesugaringEventConsumer() {

              @Override
              public void acceptNestConstructorBridge(
                  ProgramMethod target,
                  ProgramMethod bridge,
                  DexProgramClass argumentClass,
                  DexClassAndMethod context) {
                methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
              }

              @Override
              public void acceptNestFieldGetBridge(
                  ProgramField target, ProgramMethod bridge, DexClassAndMethod context) {
                methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
              }

              @Override
              public void acceptNestFieldPutBridge(
                  ProgramField target, ProgramMethod bridge, DexClassAndMethod context) {
                methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
              }

              @Override
              public void acceptNestMethodBridge(
                  ProgramMethod target, ProgramMethod bridge, DexClassAndMethod context) {
                methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
              }
            });
    ThreadUtils.processItems(
        classpathClassesInNests,
        clazz -> synthesizeBridgesForNestBasedAccessesOnClasspath(clazz, eventConsumer),
        executorService);
  }

  public void synthesizeBridgesForNestBasedAccessesOnClasspath(
      DexClasspathClass clazz, NestBasedAccessDesugaringEventConsumer eventConsumer) {
    clazz.forEachClasspathMethod(
        method ->
            method.registerCodeReferencesForDesugaring(
                new NestBasedAccessDesugaringUseRegistry(method, eventConsumer)));
  }

  private class NestBasedAccessDesugaringUseRegistry extends UseRegistry<ClasspathMethod> {

    private final NestBasedAccessDesugaringEventConsumer eventConsumer;

    NestBasedAccessDesugaringUseRegistry(
        ClasspathMethod context, NestBasedAccessDesugaringEventConsumer eventConsumer) {
      super(D8NestBasedAccessDesugaring.this.appView, context);
      this.eventConsumer = eventConsumer;
    }

    private void registerFieldAccessFromClasspath(DexField reference, boolean isGet) {
      DexClassAndField field =
          reference.lookupMemberOnClass(appView.definitionForHolder(reference));
      if (field != null && needsDesugaring(field, getContext())) {
        ensureFieldAccessBridgeFromClasspathAccess(field, isGet, eventConsumer);
      }
    }

    private void ensureFieldAccessBridgeFromClasspathAccess(
        DexClassAndField field,
        boolean isGet,
        NestBasedAccessDesugaringEventConsumer eventConsumer) {
      if (field.isProgramField()) {
        ensureFieldAccessBridgeFromClasspathAccess(field.asProgramField(), isGet, eventConsumer);
      } else if (field.isClasspathField()) {
        // Intentionally empty.
      } else {
        assert field.isLibraryField();
        throw reportIncompleteNest(field.asLibraryField());
      }
    }

    private void ensureFieldAccessBridgeFromClasspathAccess(
        ProgramField field, boolean isGet, NestBasedAccessDesugaringEventConsumer eventConsumer) {
      DexMethod bridgeReference = getFieldAccessBridgeReference(field, isGet);
      synchronized (field.getHolder().getMethodCollection()) {
        if (field.getHolder().lookupMethod(bridgeReference) == null) {
          ProgramMethod bridge =
              AccessBridgeFactory.createFieldAccessorBridge(bridgeReference, field, isGet);
          bridge.getHolder().addDirectMethod(bridge.getDefinition());
          if (isGet) {
            eventConsumer.acceptNestFieldGetBridge(field, bridge, getContext());
          } else {
            eventConsumer.acceptNestFieldPutBridge(field, bridge, getContext());
          }
        }
      }
    }

    private void registerInvokeFromClasspath(DexMethod reference) {
      if (!reference.getHolderType().isClassType()) {
        return;
      }
      DexClassAndMethod method =
          reference.lookupMemberOnClass(appView.definitionForHolder(reference));
      if (method != null && needsDesugaring(method, getContext())) {
        ensureConstructorOrMethodBridgeFromClasspathAccess(method, eventConsumer);
      }
    }

    // This is only used for generating bridge methods for class path references.
    private void ensureConstructorOrMethodBridgeFromClasspathAccess(
        DexClassAndMethod method, NestBasedAccessDesugaringEventConsumer eventConsumer) {
      if (method.isProgramMethod()) {
        if (method.getDefinition().isInstanceInitializer()) {
          ensureConstructorBridgeFromClasspathAccess(method.asProgramMethod(), eventConsumer);
        } else {
          ensureMethodBridgeFromClasspathAccess(method.asProgramMethod(), eventConsumer);
        }
      } else if (method.isClasspathMethod()) {
        if (method.getDefinition().isInstanceInitializer()) {
          ensureConstructorArgumentClass(method);
        }
      } else {
        assert method.isLibraryMethod();
        throw reportIncompleteNest(method.asLibraryMethod());
      }
    }

    private void ensureConstructorBridgeFromClasspathAccess(
        ProgramMethod method, NestBasedAccessDesugaringEventConsumer eventConsumer) {
      assert method.getDefinition().isInstanceInitializer();
      DexProgramClass constructorArgumentClass =
          ensureConstructorArgumentClass(method).asProgramClass();
      DexMethod bridgeReference = getConstructorBridgeReference(method, constructorArgumentClass);
      synchronized (method.getHolder().getMethodCollection()) {
        if (method.getHolder().lookupMethod(bridgeReference) == null) {
          ProgramMethod bridge =
              AccessBridgeFactory.createInitializerAccessorBridge(
                  bridgeReference, method, dexItemFactory);
          bridge.getHolder().addDirectMethod(bridge.getDefinition());
          eventConsumer.acceptNestConstructorBridge(
              method, bridge, constructorArgumentClass, getContext());
        }
      }
    }

    private void ensureMethodBridgeFromClasspathAccess(
        ProgramMethod method, NestBasedAccessDesugaringEventConsumer eventConsumer) {
      assert !method.getDefinition().isInstanceInitializer();
      DexMethod bridgeReference = getMethodBridgeReference(method);
      synchronized (method.getHolder().getMethodCollection()) {
        if (method.getHolder().lookupMethod(bridgeReference) == null) {
          ProgramMethod bridge =
              AccessBridgeFactory.createMethodAccessorBridge(
                  bridgeReference, method, dexItemFactory);
          bridge.getHolder().addDirectMethod(bridge.getDefinition());
          eventConsumer.acceptNestMethodBridge(method, bridge, getContext());
        }
      }
    }

    @Override
    public void registerInvokeDirect(DexMethod method) {
      registerInvokeFromClasspath(method);
    }

    @Override
    public void registerInvokeInterface(DexMethod method) {
      registerInvokeFromClasspath(method);
    }

    @Override
    public void registerInvokeStatic(DexMethod method) {
      registerInvokeFromClasspath(method);
    }

    @Override
    public void registerInvokeSuper(DexMethod method) {
      registerInvokeFromClasspath(method);
    }

    @Override
    public void registerInvokeVirtual(DexMethod method) {
      registerInvokeFromClasspath(method);
    }

    @Override
    public void registerInstanceFieldWrite(DexField field) {
      registerFieldAccessFromClasspath(field, false);
    }

    @Override
    public void registerInstanceFieldRead(DexField field) {
      registerFieldAccessFromClasspath(field, true);
    }

    @Override
    public void registerStaticFieldRead(DexField field) {
      registerFieldAccessFromClasspath(field, true);
    }

    @Override
    public void registerStaticFieldWrite(DexField field) {
      registerFieldAccessFromClasspath(field, false);
    }

    @Override
    public void registerInitClass(DexType clazz) {
      // Intentionally empty.
    }

    @Override
    public void registerInstanceOf(DexType type) {
      // Intentionally empty.
    }

    @Override
    public void registerNewInstance(DexType type) {
      // Intentionally empty.
    }

    @Override
    public void registerTypeReference(DexType type) {
      // Intentionally empty.
    }
  }
}
