// 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.naming;

import static com.android.tools.r8.utils.DescriptorUtils.JAVA_PACKAGE_SEPARATOR;
import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;

import com.android.tools.r8.dex.Constants;
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.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import org.objectweb.asm.Type;

/**
 * Stores renaming information for a member.
 *
 * <p>This includes the signature and the original name.
 */
public class MemberNaming implements MappingWithResidualInfo, Comparable<MemberNaming> {

  private static final List<ReferentialMappingInformation> EMPTY_MAPPING_INFORMATION =
      Collections.emptyList();

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof MemberNaming)) {
      return false;
    }
    MemberNaming that = (MemberNaming) o;
    return signature.equals(that.signature) && residualSignature.equals(that.residualSignature);
  }

  @Override
  public int hashCode() {
    int result = signature.hashCode();
    result = 31 * result + residualSignature.hashCode();
    return result;
  }

  /** Original signature of the member. */
  private final Signature signature;
  /** Residual signature where types and names could be changed. */
  private final Signature residualSignature;
  /** Position of the member in the file. */
  private final Position position;

  private List<ReferentialMappingInformation> additionalMappingInformation =
      EMPTY_MAPPING_INFORMATION;

  public MemberNaming(Signature signature, Signature residualSignature) {
    this(signature, residualSignature, Position.UNKNOWN);
  }

  public MemberNaming(Signature signature, Signature residualSignature, Position position) {
    this.signature = signature;
    this.residualSignature = residualSignature;
    this.position = position;
  }

  /** This is used internally in google3. */
  @Deprecated
  public Signature getRenamedSignature() {
    return residualSignature;
  }

  @Override
  public Signature getOriginalSignature() {
    return signature;
  }

  public String getOriginalName() {
    return signature.name;
  }

  @Override
  public boolean hasResidualSignatureMappingInformation() {
    return Iterables.any(
        additionalMappingInformation, MappingInformation::isResidualSignatureMappingInformation);
  }

  @Override
  public String getRenamedName() {
    return residualSignature.getName();
  }

  public boolean isMethodNaming() {
    return signature.kind() == SignatureKind.METHOD;
  }

  public boolean isFieldNaming() {
    return signature.kind() == SignatureKind.FIELD;
  }

  public Position getPosition() {
    return position;
  }

  @Override
  public String toString() {
    return signature.toString() + " -> " + residualSignature.getName();
  }

  @Override
  public Signature getResidualSignature() {
    return residualSignature;
  }

  public void addMappingInformation(
      ReferentialMappingInformation info, Consumer<MappingInformation> onProhibitedAddition) {
    if (additionalMappingInformation == EMPTY_MAPPING_INFORMATION) {
      additionalMappingInformation = new ArrayList<>();
    }
    MappingInformation.addMappingInformation(
        additionalMappingInformation, info, onProhibitedAddition);
  }

  public void addAllMappingInformation(List<ReferentialMappingInformation> infos) {
    Consumer<MappingInformation> emptyConsumer = ConsumerUtils.emptyConsumer();
    for (ReferentialMappingInformation mappingInformation : infos) {
      addMappingInformation(mappingInformation, emptyConsumer);
    }
  }

  public boolean isCompilerSynthesized() {
    for (MappingInformation info : additionalMappingInformation) {
      if (info.isCompilerSynthesizedMappingInformation() || info.isOutlineMappingInformation()) {
        return true;
      }
    }
    return false;
  }

  public boolean isOutlineFrame() {
    for (MappingInformation info : additionalMappingInformation) {
      if (info.isOutlineMappingInformation()) {
        return true;
      }
    }
    return false;
  }

  public List<ReferentialMappingInformation> getAdditionalMappingInformation() {
    return additionalMappingInformation;
  }

  @Override
  public int compareTo(MemberNaming other) {
    return Comparator.comparing(MemberNaming::isFieldNaming)
        .thenComparing(MemberNaming::getRenamedName)
        .thenComparing(MemberNaming::getOriginalName)
        .thenComparing(memberNaming -> getOriginalSignature().toString())
        .compare(this, other);
  }

  public abstract static class Signature {

    public final String name;

    protected Signature(String name) {
      this.name = name;
    }

    abstract Signature asRenamed(String renamedName);

    abstract public SignatureKind kind();

    @Override
    abstract public boolean equals(Object o);

    @Override
    abstract public int hashCode();

    abstract void write(Writer builder) throws IOException;

    public abstract Signature computeResidualSignature(
        String renamedName, Function<String, String> typeNameMapper);

    public abstract Signature toUnqualifiedSignature();

    public abstract Signature toQualifiedSignature(String holder);

    public boolean isQualified() {
      return name.indexOf(JAVA_PACKAGE_SEPARATOR) != -1;
    }

    public String toUnqualifiedName() {
      assert isQualified();
      return name.substring(name.lastIndexOf(JAVA_PACKAGE_SEPARATOR) + 1);
    }

    public String toHolderFromQualified() {
      assert isQualified();
      return name.substring(0, name.lastIndexOf(JAVA_PACKAGE_SEPARATOR));
    }

    public boolean isMethodSignature() {
      return false;
    }

    public boolean isFieldSignature() {
      return false;
    }

    public MethodSignature asMethodSignature() {
      return null;
    }

    public FieldSignature asFieldSignature() {
      return null;
    }

    @Override
    public String toString() {
      try {
        StringWriter writer = new StringWriter();
        write(writer);
        return writer.toString();
      } catch (IOException e) {
        // StringWriter is not throwing IOException
        throw new Unreachable(e);
      }
    }

    public String getName() {
      return name;
    }

    enum SignatureKind {
      METHOD,
      FIELD
    }
  }

  public static class FieldSignature extends Signature {

    public final String type;

    public FieldSignature(String name, String type) {
      super(name);
      this.type = type;
    }

    public static FieldSignature fromDexField(DexField field) {
      return fromDexField(field, false);
    }

    public static FieldSignature fromDexField(DexField field, boolean withQualifiedName) {
      return new FieldSignature(
          withQualifiedName ? field.qualifiedName() : field.name.toSourceString(),
          field.type.toSourceString());
    }

    public static FieldSignature fromFieldReference(FieldReference fieldReference) {
      return new FieldSignature(
          fieldReference.getFieldName(), fieldReference.getFieldType().getTypeName());
    }

    public DexField toDexField(DexItemFactory factory, DexType clazz) {
      return factory.createField(
          clazz,
          factory.createType(javaTypeToDescriptor(type)),
          factory.createString(name));
    }

    @Override
    Signature asRenamed(String renamedName) {
      return new FieldSignature(renamedName, type);
    }

    @Override
    public SignatureKind kind() {
      return SignatureKind.FIELD;
    }

    @Override
    public FieldSignature computeResidualSignature(
        String renamedName, Function<String, String> typeNameMapper) {
      return new FieldSignature(renamedName, DescriptorUtils.mapTypeName(type, typeNameMapper));
    }

    @Override
    public Signature toUnqualifiedSignature() {
      return new FieldSignature(toUnqualifiedName(), type);
    }

    @Override
    public Signature toQualifiedSignature(String holder) {
      assert !isQualified();
      return new FieldSignature(holder + "." + name, type);
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof FieldSignature)) {
        return false;
      }
      FieldSignature that = (FieldSignature) o;
      return name.equals(that.name) && type.equals(that.type);
    }

    @Override
    public int hashCode() {
      return name.hashCode() * 31 + type.hashCode();
    }

    @Override
    public String toString() {
      return type + " " + name;
    }

    @Override
    void write(Writer writer) throws IOException {
      writer.append(type);
      writer.append(' ');
      writer.append(name);
    }

    @Override
    public boolean isFieldSignature() {
      return true;
    }

    @Override
    public FieldSignature asFieldSignature() {
      return this;
    }
  }

  public static class MethodSignature extends Signature {

    public final String type;
    public final String[] parameters;

    public MethodSignature(String name, String type, String[] parameters) {
      super(name);
      this.type = type;
      this.parameters = parameters;
    }

    public MethodSignature(String name, String type, Collection<String> parameters) {
      super(name);
      this.type = type;
      this.parameters = parameters.toArray(StringUtils.EMPTY_ARRAY);
    }

    public static MethodSignature fromDexMethod(DexMethod method) {
      return fromDexMethod(method, false);
    }

    public static MethodSignature fromDexMethod(DexMethod method, boolean withQualifiedName) {
      String[] paramNames = new String[method.getArity()];
      DexType[] values = method.proto.parameters.values;
      for (int i = 0; i < values.length; i++) {
        paramNames[i] = values[i].toSourceString();
      }
      return new MethodSignature(
          withQualifiedName ? method.qualifiedName() : method.name.toSourceString(),
          method.proto.returnType.toSourceString(),
          paramNames);
    }

    public static MethodSignature fromSignature(String name, String signature) {
      Type returnDescriptor = Type.getReturnType(signature);
      return new MethodSignature(
          name,
          DescriptorUtils.descriptorToJavaType(returnDescriptor.getDescriptor()),
          ArrayUtils.mapToStringArray(
              Type.getArgumentTypes(signature),
              param -> DescriptorUtils.descriptorToJavaType(param.getDescriptor())));
    }

    public static MethodSignature fromMethodReference(MethodReference reference) {
      TypeReference returnType = reference.getReturnType();
      return new MethodSignature(
          reference.getMethodName(),
          returnType == null ? "void" : returnType.getTypeName(),
          CollectionUtils.mapToStringArray(reference.getFormalTypes(), TypeReference::getTypeName));
    }

    public MethodSignature toUnqualified() {
      assert isQualified();
      return new MethodSignature(toUnqualifiedName(), type, parameters);
    }

    public DexMethod toDexMethod(DexItemFactory factory, DexType clazz) {
      DexType[] paramTypes = new DexType[parameters.length];
      for (int i = 0; i < parameters.length; i++) {
        paramTypes[i] = factory.createType(javaTypeToDescriptor(parameters[i]));
      }
      DexType returnType = factory.createType(javaTypeToDescriptor(type));
      return factory.createMethod(
          clazz,
          factory.createProto(returnType, paramTypes),
          factory.createString(name));
    }

    public static MethodSignature initializer(String[] parameters) {
      return new MethodSignature(Constants.INSTANCE_INITIALIZER_NAME, "void", parameters);
    }

    @Override
    MethodSignature asRenamed(String renamedName) {
      return new MethodSignature(renamedName, type, parameters);
    }

    @Override
    public SignatureKind kind() {
      return SignatureKind.METHOD;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof MethodSignature)) {
        return false;
      }

      MethodSignature that = (MethodSignature) o;
      return type.equals(that.type)
          && name.equals(that.name)
          && Arrays.equals(parameters, that.parameters);
    }

    @Override
    public int hashCode() {
      return (type.hashCode() * 17
          + name.hashCode()) * 31
          + Arrays.hashCode(parameters);
    }

    @Override
    public String toString() {
        return type + ' ' + name + '(' + String.join(",", parameters) + ')';
    }

    @Override
    void write(Writer writer) throws IOException {
      writer.append(type)
          .append(' ')
          .append(name)
          .append('(');
      for (int i = 0; i < parameters.length; i++) {
        writer.append(parameters[i]);
        if (i < parameters.length - 1) {
          writer.append(',');
        }
      }
      writer.append(')');
    }

    public String toDescriptor() {
      StringBuilder sb = new StringBuilder();
      sb.append('(');
      for (String parameterType : parameters) {
        sb.append(javaTypeToDescriptor(parameterType));
      }
      sb.append(')');
      sb.append(javaTypeToDescriptor(type));
      return sb.toString();
    }

    @Override
    public MethodSignature computeResidualSignature(
        String renamedName, Function<String, String> typeNameMapper) {
      return new MethodSignature(
          renamedName,
          DescriptorUtils.mapTypeName(type, typeNameMapper),
          ArrayUtils.mapToStringArray(
              parameters,
              parameterTypeName -> DescriptorUtils.mapTypeName(parameterTypeName, typeNameMapper)));
    }

    @Override
    public Signature toUnqualifiedSignature() {
      return new MethodSignature(toUnqualifiedName(), type, parameters);
    }

    @Override
    public Signature toQualifiedSignature(String holder) {
      return new MethodSignature(holder + "." + name, type, parameters);
    }

    @Override
    public boolean isMethodSignature() {
      return true;
    }

    @Override
    public MethodSignature asMethodSignature() {
      return this;
    }
  }
}
