// Copyright (c) 2017, 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.errors.Unreachable;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// Source code representing synthesized lambda main method
final class LambdaMainMethodSourceCode extends SynthesizedLambdaSourceCode {

  LambdaMainMethodSourceCode(LambdaClass lambda, DexMethod mainMethod) {
    super(lambda, mainMethod);
  }

  private boolean checkSignatures(
      DexType[] captures, DexType[] enforcedParams, DexType enforcedReturnType,
      List<DexType> implReceiverAndArgs, DexType implReturnType) {
    List<DexType> capturesAndParams = new ArrayList<>();
    capturesAndParams.addAll(Lists.newArrayList(captures));
    capturesAndParams.addAll(Lists.newArrayList(enforcedParams));

    int size = capturesAndParams.size();
    if (size != implReceiverAndArgs.size()) {
      return false;
    }

    for (int i = 0; i < size; i++) {
      if (!isSameOrAdaptableTo(capturesAndParams.get(i), implReceiverAndArgs.get(i))) {
        return false;
      }
    }

    if (!enforcedReturnType.isVoidType()
        && !isSameOrAdaptableTo(implReturnType, enforcedReturnType)) {
      return false;
    }
    return true;
  }

  private DexType getPrimitiveFromBoxed(DexType boxedPrimitive) {
    DexString descriptor = boxedPrimitive.descriptor;
    DexItemFactory factory = factory();
    if (descriptor == factory.boxedBooleanDescriptor) {
      return factory.booleanType;
    }
    if (descriptor == factory.boxedByteDescriptor) {
      return factory.byteType;
    }
    if (descriptor == factory.boxedCharDescriptor) {
      return factory.charType;
    }
    if (descriptor == factory.boxedShortDescriptor) {
      return factory.shortType;
    }
    if (descriptor == factory.boxedIntDescriptor) {
      return factory.intType;
    }
    if (descriptor == factory.boxedLongDescriptor) {
      return factory.longType;
    }
    if (descriptor == factory.boxedFloatDescriptor) {
      return factory.floatType;
    }
    if (descriptor == factory.boxedDoubleDescriptor) {
      return factory.doubleType;
    }
    return null;
  }

  private DexType getBoxedForPrimitiveType(DexType primitive) {
    switch (primitive.descriptor.content[0]) {
      case 'Z':  // byte
        return factory().boxedBooleanType;
      case 'B':  // byte
        return factory().boxedByteType;
      case 'S':  // short
        return factory().boxedShortType;
      case 'C':  // char
        return factory().boxedCharType;
      case 'I':  // int
        return factory().boxedIntType;
      case 'J':  // long
        return factory().boxedLongType;
      case 'F':  // float
        return factory().boxedFloatType;
      case 'D':  // double
        return factory().boxedDoubleType;
      default:
        throw new Unreachable("Invalid primitive type descriptor: " + primitive);
    }
  }

  // Checks if the types are the same OR type `a` is adaptable to type `b`.
  private boolean isSameOrAdaptableTo(DexType a, DexType b) {
    if (a == b) {
      return true;
    }

    DexItemFactory factory = factory();
    if (a.isArrayType()) {
      // Arrays are only adaptable to java.lang.Object or other arrays, note that we
      // don't check element type inheritance in the second case since we assume the
      // input code is verifiable.
      return b == factory.objectType || b.isArrayType();
    }

    if (a.isPrimitiveType()) {
      if (b.isPrimitiveType()) {
        return isSameOrAdaptableTo(a.descriptor.content[0], b.descriptor.content[0]);
      }

      // `a` is primitive and `b` is a supertype of the boxed type `a`.
      DexType boxedPrimitiveType = getBoxedForPrimitiveType(a);
      if (b == boxedPrimitiveType ||
          b == factory.objectType ||
          b == factory.serializableType ||
          b == factory.comparableType) {
        return true;
      }
      return boxedPrimitiveType != factory.boxedCharType
          && boxedPrimitiveType != factory.boxedBooleanType
          && b.descriptor == factory.boxedNumberDescriptor;
    }

    if (b.isPrimitiveType()) {
      if (a == factory.objectType) {
        // `a` is java.lang.Object in which case we assume it represented by
        // proper boxed type.
        return true;
      }
      // `a` is a boxed type for `a*` which can be
      // widened to primitive type `b`.
      DexType unboxedA = getPrimitiveFromBoxed(a);
      return unboxedA != null &&
          isSameOrAdaptableTo(unboxedA.descriptor.content[0], b.descriptor.content[0]);
    }

    // Otherwise `a` should be a reference type derived from `b`.
    // NOTE: we don't check `b` for being actually a supertype, since we
    // might not have full classpath with inheritance information to do that.
    // We assume this requirement stands and will be caught by cast
    // instruction anyways in most cases.
    return a.isClassType() && b.isClassType();
  }

  // For two primitive types `a` is adjustable to `b` iff `a` is the same as `b`
  // or can be converted to `b` via a primitive widening conversion.
  private boolean isSameOrAdaptableTo(byte from, byte to) {
    if (from == to) {
      return true;
    }
    switch (from) {
      case 'B':  // byte
        return to == 'S' || to == 'I' || to == 'J' || to == 'F' || to == 'D';
      case 'S':  // short
      case 'C':  // char
        return to == 'I' || to == 'J' || to == 'F' || to == 'D';
      case 'I':  // int
        return to == 'J' || to == 'F' || to == 'D';
      case 'J':  // long
        return to == 'F' || to == 'D';
      case 'F':  // float
        return to == 'D';
      case 'Z':  // boolean
      case 'D':  // double
        return false;
      default:
        throw new Unreachable("Invalid primitive type descriptor: " + from);
    }
  }

  @Override
  protected void prepareInstructions() {
    DexType[] capturedTypes = captures();
    DexType[] erasedParams = descriptor().erasedProto.parameters.values;
    DexType erasedReturnType = descriptor().erasedProto.returnType;
    DexType[] enforcedParams = descriptor().enforcedProto.parameters.values;
    DexType enforcedReturnType = descriptor().enforcedProto.returnType;

    LambdaClass.Target target = lambda.target;
    DexMethod methodToCall = target.callTarget;

    // Only constructor call should use direct invoke type since super
    // and private methods require accessor methods.
    boolean constructorTarget = target.invokeType == Invoke.Type.DIRECT;
    assert !constructorTarget || methodToCall.name == factory().constructorMethodName;

    List<DexType> implReceiverAndArgs = new ArrayList<>();
    if (target.invokeType == Invoke.Type.VIRTUAL || target.invokeType == Invoke.Type.INTERFACE) {
      implReceiverAndArgs.add(methodToCall.holder);
    }
    implReceiverAndArgs.addAll(Lists.newArrayList(methodToCall.proto.parameters.values));
    DexType implReturnType = methodToCall.proto.returnType;

    assert target.invokeType == Invoke.Type.STATIC
        || target.invokeType == Invoke.Type.VIRTUAL
        || target.invokeType == Invoke.Type.DIRECT
        || target.invokeType == Invoke.Type.INTERFACE;
    assert checkSignatures(capturedTypes, enforcedParams,
        enforcedReturnType, implReceiverAndArgs,
        constructorTarget ? target.callTarget.holder : implReturnType);

    // Prepare call arguments.
    List<ValueType> argValueTypes = new ArrayList<>();
    List<Integer> argRegisters = new ArrayList<>();

    // If the target is a constructor, we need to create the instance first.
    // This instance will be the first argument to the call.
    if (constructorTarget) {
      int instance = nextRegister(ValueType.OBJECT);
      add(builder -> builder.addNewInstance(instance, methodToCall.holder));
      argValueTypes.add(ValueType.OBJECT);
      argRegisters.add(instance);
    }

    // Load captures if needed.
    int capturedValues = capturedTypes.length;
    for (int i = 0; i < capturedValues; i++) {
      ValueType valueType = ValueType.fromDexType(capturedTypes[i]);
      int register = nextRegister(valueType);

      argValueTypes.add(valueType);
      argRegisters.add(register);

      // Read field into tmp local.
      DexField field = lambda.getCaptureField(i);
      add(builder -> builder.addInstanceGet(register, getReceiverRegister(), field));
    }

    // Prepare arguments.
    for (int i = 0; i < erasedParams.length; i++) {
      DexType expectedParamType = implReceiverAndArgs.get(i + capturedValues);
      argValueTypes.add(ValueType.fromDexType(expectedParamType));
      argRegisters.add(prepareParameterValue(
          getParamRegister(i), erasedParams[i], enforcedParams[i], expectedParamType));
    }

    // Method call to the method implementing lambda or method-ref.
    add(builder -> builder.addInvoke(target.invokeType,
        methodToCall, methodToCall.proto, argValueTypes, argRegisters));

    // Does the method have return value?
    if (enforcedReturnType.isVoidType()) {
      add(IRBuilder::addReturn);
    } else if (constructorTarget) {
      // Return newly created instance
      int instanceRegister = argRegisters.get(0);
      int adjustedValue = prepareReturnValue(instanceRegister,
          erasedReturnType, enforcedReturnType, methodToCall.holder);
      add(builder -> builder.addReturn(
          ValueType.fromDexType(erasedReturnType), adjustedValue));
    } else {
      ValueType implValueType = ValueType.fromDexType(implReturnType);
      int tempValue = nextRegister(implValueType);
      add(builder -> builder.addMoveResult(tempValue));
      int adjustedValue = prepareReturnValue(tempValue,
          erasedReturnType, enforcedReturnType, methodToCall.proto.returnType);
      ValueType adjustedValueType = ValueType.fromDexType(erasedReturnType);
      add(builder -> builder.addReturn(adjustedValueType, adjustedValue));
    }
  }

  // Adds necessary casts and transformations to adjust the value
  // returned by impl-method to expected return type of the method.
  private int prepareReturnValue(int register,
      DexType erasedType, DexType enforcedType, DexType actualType) {
    // `actualType` must be adjusted to `enforcedType` first.
    register = adjustType(register, actualType, enforcedType, true);

    // `erasedType` and `enforcedType` may only differ when they both
    // are class types and `erasedType` is a base type of `enforcedType`,
    // so no transformation is actually needed.
    assert LambdaDescriptor.isSameOrDerived(factory(), enforcedType, erasedType);
    return register;
  }

  // Adds necessary casts and transformations to adjust parameter
  // value to the expected type of method-impl argument.
  //
  // Note that the original parameter type (`erasedType`) may need to
  // be converted to enforced parameter type (`enforcedType`), which,
  // in its turn, may need to be adjusted to the parameter type of
  // the impl-method (`expectedType`).
  private int prepareParameterValue(int register,
      DexType erasedType, DexType enforcedType, DexType expectedType) {
    register = enforceParameterType(register, erasedType, enforcedType);
    register = adjustType(register, enforcedType, expectedType, false);
    return register;
  }

  private int adjustType(int register, DexType fromType, DexType toType, boolean returnType) {
    if (fromType == toType) {
      return register;
    }

    boolean fromTypePrimitive = fromType.isPrimitiveType();
    boolean toTypePrimitive = toType.isPrimitiveType();

    // If both are primitive they must be convertible via primitive widening conversion.
    if (fromTypePrimitive && toTypePrimitive) {
      return addPrimitiveWideningConversion(register, fromType, toType);
    }

    // If the first one is a boxed primitive type and the second one is a primitive
    // type, the value must be unboxed and converted to the resulting type via primitive
    // widening conversion.
    if (toTypePrimitive) {
      DexType boxedType = fromType;
      if (boxedType == factory().objectType) {
        // We are in situation when from(=java.lang.Object) is being adjusted to a
        // primitive type, in which case we assume it is of proper box type.
        boxedType = getBoxedForPrimitiveType(toType);
        register = castToBoxedType(register, boxedType);
      }
      DexType fromTypeAsPrimitive = getPrimitiveFromBoxed(boxedType);
      if (fromTypeAsPrimitive != null) {
        int unboxedRegister = addPrimitiveUnboxing(register, fromTypeAsPrimitive, boxedType);
        return addPrimitiveWideningConversion(unboxedRegister, fromTypeAsPrimitive, toType);
      }
    }

    // If the first one is a primitive type and the second one is a boxed
    // type for this primitive type, just box the value.
    if (fromTypePrimitive) {
      DexType boxedFromType = getBoxedForPrimitiveType(fromType);
      if (toType == boxedFromType ||
          toType == factory().objectType ||
          toType == factory().serializableType ||
          toType == factory().comparableType ||
          (boxedFromType != factory().booleanType &&
              boxedFromType != factory().charType &&
              toType == factory().boxedNumberType)) {
        return addPrimitiveBoxing(register, fromType, boxedFromType);
      }
    }

    if (fromType.isArrayType() && (toType == factory().objectType || toType.isArrayType())) {
      // If `fromType` is an array and `toType` is java.lang.Object, no cast is needed.
      // If both `fromType` and `toType` are arrays, no cast is needed since we assume
      // the input code is verifiable.
      return register;
    }

    if (fromType.isClassType() && toType.isClassType()) {
      if (returnType) {
        // For return type adjustment in case `fromType` and `toType` are both reference types,
        // `fromType` does NOT have to be deriving from `toType` and we need to add a cast.
        // NOTE: we don't check `toType` for being actually a supertype, since we
        // might not have full classpath with inheritance information to do that.
        int finalRegister = register;
        add(builder -> builder.addCheckCast(finalRegister, toType));
      }
      return register;
    }

    throw new Unreachable("Unexpected type adjustment from "
        + fromType.toSourceString() + " to " + toType);
  }

  private int addPrimitiveWideningConversion(int register, DexType fromType, DexType toType) {
    assert fromType.isPrimitiveType() && toType.isPrimitiveType();
    if (fromType == toType) {
      return register;
    }

    NumericType from = NumericType.fromDexType(fromType);
    NumericType to = NumericType.fromDexType(toType);

    if (from != null && to != null) {
      assert from != to;

      switch (to) {
        case SHORT: {
          if (from != NumericType.BYTE) {
            break; // Only BYTE can be converted to SHORT via widening conversion.
          }
          int result = nextRegister(ValueType.INT);
          add(builder -> builder.addConversion(to, NumericType.INT, result, register));
          return result;
        }

        case INT:
          if (from == NumericType.BYTE || from == NumericType.CHAR || from == NumericType.SHORT) {
            return register; // No actual conversion is needed.
          }
          break;

        case LONG: {
          if (from == NumericType.FLOAT || from == NumericType.DOUBLE) {
            break; // Not a widening conversion.
          }
          int result = nextRegister(ValueType.LONG);
          add(builder -> builder.addConversion(to, NumericType.INT, result, register));
          return result;
        }

        case FLOAT: {
          if (from == NumericType.DOUBLE) {
            break; // Not a widening conversion.
          }
          int result = nextRegister(ValueType.FLOAT);
          NumericType type = (from == NumericType.LONG) ? NumericType.LONG : NumericType.INT;
          add(builder -> builder.addConversion(to, type, result, register));
          return result;
        }

        case DOUBLE: {
          int result = nextRegister(ValueType.DOUBLE);
          NumericType type = (from == NumericType.FLOAT || from == NumericType.LONG)
              ? from : NumericType.INT;
          add(builder -> builder.addConversion(to, type, result, register));
          return result;
        }
        default:
          // exception is thrown below
          break;
      }
    }

    throw new Unreachable("Type " + fromType.toSourceString() + " cannot be " +
        "converted to " + toType.toSourceString() + " via primitive widening conversion.");
  }

  private DexMethod getUnboxMethod(byte primitive, DexType boxType) {
    DexItemFactory factory = factory();
    DexProto proto;
    switch (primitive) {
      case 'Z':  // byte
        proto = factory.createProto(factory.booleanType);
        return factory.createMethod(boxType, proto, factory.unboxBooleanMethodName);
      case 'B':  // byte
        proto = factory.createProto(factory.byteType);
        return factory.createMethod(boxType, proto, factory.unboxByteMethodName);
      case 'S':  // short
        proto = factory.createProto(factory.shortType);
        return factory.createMethod(boxType, proto, factory.unboxShortMethodName);
      case 'C':  // char
        proto = factory.createProto(factory.charType);
        return factory.createMethod(boxType, proto, factory.unboxCharMethodName);
      case 'I':  // int
        proto = factory.createProto(factory.intType);
        return factory.createMethod(boxType, proto, factory.unboxIntMethodName);
      case 'J':  // long
        proto = factory.createProto(factory.longType);
        return factory.createMethod(boxType, proto, factory.unboxLongMethodName);
      case 'F':  // float
        proto = factory.createProto(factory.floatType);
        return factory.createMethod(boxType, proto, factory.unboxFloatMethodName);
      case 'D':  // double
        proto = factory.createProto(factory.doubleType);
        return factory.createMethod(boxType, proto, factory.unboxDoubleMethodName);
      default:
        throw new Unreachable("Invalid primitive type descriptor: " + primitive);
    }
  }

  private int addPrimitiveUnboxing(int register, DexType primitiveType, DexType boxType) {
    DexMethod method = getUnboxMethod(primitiveType.descriptor.content[0], boxType);

    List<ValueType> argValueTypes = Collections.singletonList(ValueType.OBJECT);
    List<Integer> argRegisters = Collections.singletonList(register);
    add(builder -> builder.addInvoke(Invoke.Type.VIRTUAL,
        method, method.proto, argValueTypes, argRegisters));

    ValueType valueType = ValueType.fromDexType(primitiveType);
    int result = nextRegister(valueType);
    add(builder -> builder.addMoveResult(result));
    return result;
  }

  private int castToBoxedType(int register, DexType boxType) {
    add(builder -> builder.addCheckCast(register, boxType));
    return register;
  }

  private int addPrimitiveBoxing(int register, DexType primitiveType, DexType boxType) {
    // Generate factory method fo boxing.
    DexItemFactory factory = factory();
    DexProto proto = factory.createProto(boxType, primitiveType);
    DexMethod method = factory.createMethod(boxType, proto, factory.valueOfMethodName);

    ValueType valueType = ValueType.fromDexType(primitiveType);
    List<ValueType> argValueTypes = Collections.singletonList(valueType);
    List<Integer> argRegisters = Collections.singletonList(register);
    add(builder -> builder.addInvoke(Invoke.Type.STATIC,
        method, method.proto, argValueTypes, argRegisters));

    int result = nextRegister(ValueType.OBJECT);
    add(builder -> builder.addMoveResult(result));
    return result;
  }
}
