// Copyright (c) 2016, 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.graph;

import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
import com.android.tools.r8.utils.InternalOptions;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.objectweb.asm.Type;

/**
 * Common structures used while reading in a Java application from jar files.
 *
 * The primary use of this class is to canonicalize dex items during read.
 * The addition of classes to the builder also takes place through this class.
 * It does not currently support multithreaded reading.
 */
public class JarApplicationReader {
  public final InternalOptions options;

  ConcurrentHashMap<String, DexString> stringCache = new ConcurrentHashMap<>();

  public JarApplicationReader(InternalOptions options) {
    this.options = options;
  }

  public DexItemFactory getFactory() {
    return options.itemFactory;
  }

  public DexString getString(String string) {
    return stringCache.computeIfAbsent(string, options.itemFactory::createString);
  }

  public DexType getType(Type type) {
    return getTypeFromDescriptor(type.getDescriptor());
  }

  public DexType getTypeFromName(String name) {
    assert isValidInternalName(name);
    return getType(Type.getObjectType(name));
  }

  public DexType getTypeFromDescriptor(String desc) {
    assert isValidDescriptor(desc);
    return options.itemFactory.createType(getString(desc));
  }

  public DexTypeList getTypeListFromNames(String[] names) {
    if (names.length == 0) {
      return DexTypeList.empty();
    }
    DexType[] types = new DexType[names.length];
    for (int i = 0; i < names.length; i++) {
      types[i] = getTypeFromName(names[i]);
    }
    return new DexTypeList(types);
  }

  public DexTypeList getTypeListFromDescriptors(String[] descriptors) {
    if (descriptors.length == 0) {
      return DexTypeList.empty();
    }
    DexType[] types = new DexType[descriptors.length];
    for (int i = 0; i < descriptors.length; i++) {
      types[i] = getTypeFromDescriptor(descriptors[i]);
    }
    return new DexTypeList(types);
  }

  public DexField getField(String owner, String name, String desc) {
    return getField(getTypeFromName(owner), name, desc);
  }

  public DexField getField(DexType owner, String name, String desc) {
    return options.itemFactory.createField(owner, getTypeFromDescriptor(desc), getString(name));
  }

  public DexMethod getMethod(String owner, String name, String desc) {
    return getMethod(getTypeFromName(owner), name, desc);
  }

  public DexMethod getMethod(DexType owner, String name, String desc) {
    return options.itemFactory.createMethod(owner, getProto(desc), getString(name));
  }

  public DexCallSite getCallSite(String methodName, String methodProto,
      DexMethodHandle bootstrapMethod, List<DexValue> bootstrapArgs) {
    return options.itemFactory.createCallSite(
        getString(methodName), getProto(methodProto), bootstrapMethod, bootstrapArgs);
  }

  public DexMethodHandle getMethodHandle(
      MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod) {
    return options.itemFactory.createMethodHandle(type, fieldOrMethod);
  }

  public DexProto getProto(String desc) {
    assert isValidDescriptor(desc);
    Type returnType = Type.getReturnType(desc);
    Type[] arguments = Type.getArgumentTypes(desc);

    StringBuilder shortyDescriptor = new StringBuilder();
    String[] argumentDescriptors = new String[arguments.length];
    shortyDescriptor.append(getShortyDescriptor(returnType));
    for (int i = 0; i < arguments.length; i++) {
      shortyDescriptor.append(getShortyDescriptor(arguments[i]));
      argumentDescriptors[i] = arguments[i].getDescriptor();
    }
    DexProto proto = options.itemFactory.createProto(
        getString(shortyDescriptor.toString()),
        getTypeFromDescriptor(returnType.getDescriptor()),
        getTypeListFromDescriptors(argumentDescriptors));
    return proto;
  }

  private static String getShortyDescriptor(Type type) {
    switch (type.getSort()) {
      case Type.METHOD:
        throw new InternalCompilerError("Cannot produce a shorty decriptor for methods");
      case Type.ARRAY:
      case Type.OBJECT:
        return "L";
      default:
        return type.getDescriptor();
    }
  }

  private boolean isValidDescriptor(String desc) {
    return Type.getType(desc).getDescriptor().equals(desc);
  }

  private boolean isValidInternalName(String name) {
    return Type.getObjectType(name).getInternalName().equals(name);
  }
}
