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

import com.android.tools.r8.graph.AppView;
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.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

// Summary:
// - Process all methods compiled rewriting nest based access (Methods processed concurrently).
// - Process classes on class path in reachable nests to find bridges to add
//    in Program classes (Nests processed concurrently).
// - Add bridges and nest constructor class (Sequential).
// - Optimize bridges (Bridges processed concurrently).
public class D8NestBasedAccessDesugaring extends NestBasedAccessDesugaring {

  // Maps a nest host to a class met which has that nest host.
  // The value is used because the nest host might be missing.
  private final Map<DexType, DexClass> metNestHosts = new ConcurrentHashMap<>();

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

  public void rewriteNestBasedAccesses(
      DexEncodedMethod encodedMethod, IRCode code, AppView<?> appView) {
    DexClass currentClass = appView.definitionFor(encodedMethod.method.holder);
    assert currentClass != null;
    if (!currentClass.isInANest()) {
      return;
    }
    metNestHosts.put(currentClass.getNestHost(), currentClass);

    ListIterator<BasicBlock> blocks = code.listIterator();
    while (blocks.hasNext()) {
      BasicBlock block = blocks.next();
      InstructionListIterator instructions = block.listIterator(code);
      while (instructions.hasNext()) {
        Instruction instruction = instructions.next();
        if (instruction.isInvokeMethod()) {
          InvokeMethod invokeMethod = instruction.asInvokeMethod();
          DexMethod methodCalled = invokeMethod.getInvokedMethod();
          DexEncodedMethod encodedMethodCalled =
              methodCalled.holder.isClassType() ? appView.definitionFor(methodCalled) : null;
          if (encodedMethodCalled != null
              && invokeRequiresRewriting(encodedMethodCalled, currentClass)) {
            DexMethod bridge = ensureInvokeBridge(encodedMethodCalled);
            if (encodedMethodCalled.isInstanceInitializer()) {
              instructions.previous();
              Value extraNullValue =
                  instructions.insertConstNullInstruction(code, appView.options());
              instructions.next();
              List<Value> parameters = new ArrayList<>(invokeMethod.arguments());
              parameters.add(extraNullValue);
              instructions.replaceCurrentInstruction(
                  new InvokeDirect(bridge, invokeMethod.outValue(), parameters));
            } else {
              instructions.replaceCurrentInstruction(
                  new InvokeStatic(bridge, invokeMethod.outValue(), invokeMethod.arguments()));
            }
          }

        } else if (instruction.isFieldInstruction()) {
          DexEncodedField encodedField =
              appView.definitionFor(instruction.asFieldInstruction().getField());
          if (encodedField != null && fieldAccessRequiresRewriting(encodedField, currentClass)) {
            if (instruction.isInstanceGet() || instruction.isStaticGet()) {
              DexMethod bridge = ensureFieldAccessBridge(encodedField, true);
              instructions.replaceCurrentInstruction(
                  new InvokeStatic(bridge, instruction.outValue(), instruction.inValues()));
            } else {
              assert instruction.isInstancePut() || instruction.isStaticPut();
              DexMethod bridge = ensureFieldAccessBridge(encodedField, false);
              instructions.replaceCurrentInstruction(
                  new InvokeStatic(bridge, instruction.outValue(), instruction.inValues()));
            }
          }
        }
      }
    }
  }

  private void processNestsConcurrently(ExecutorService executorService) throws ExecutionException {
    List<Future<?>> futures = new ArrayList<>();
    for (DexClass clazz : metNestHosts.values()) {
      futures.add(asyncProcessNest(clazz, executorService));
    }
    ThreadUtils.awaitFutures(futures);
  }

  private void addDeferredBridges() {
    addDeferredBridges(bridges.values());
    addDeferredBridges(getFieldBridges.values());
    addDeferredBridges(putFieldBridges.values());
  }

  private void addDeferredBridges(Collection<DexEncodedMethod> bridges) {
    for (DexEncodedMethod bridge : bridges) {
      DexClass holder = definitionFor(bridge.method.holder);
      assert holder != null && holder.isProgramClass();
      holder.asProgramClass().addMethod(bridge);
    }
  }

  private void optimizeDeferredBridgesConcurrently(
      ExecutorService executorService, IRConverter converter) throws ExecutionException {
    Collection<DexEncodedMethod> methods = new ArrayList<>();
    methods.addAll(bridges.values());
    methods.addAll(getFieldBridges.values());
    methods.addAll(putFieldBridges.values());
    converter.processMethodsConcurrently(methods, executorService);
  }

  public void desugarNestBasedAccess(
      DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
      throws ExecutionException {
    processNestsConcurrently(executorService);
    addDeferredBridges();
    synthesizeNestConstructor(builder);
    optimizeDeferredBridgesConcurrently(executorService, converter);
  }

  // In D8, programClass are processed on the fly so they do not need to be processed again here.
  @Override
  protected boolean shouldProcessClassInNest(DexClass clazz, List<DexType> nest) {
    return clazz.isNotProgramClass();
  }

  @Override
  void reportMissingNestHost(DexClass clazz) {
    appView.options().nestDesugaringWarningMissingNestHost(clazz);
  }

  @Override
  void reportIncompleteNest(List<DexType> nest) {
    appView.options().nestDesugaringWarningIncompleteNest(nest, appView);
  }
}
