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

import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;

public class AppInfo {

  public final DexApplication app;
  public final DexItemFactory dexItemFactory;
  private final ConcurrentHashMap<DexType, Map<Descriptor, KeyedDexItem>> definitions =
      new ConcurrentHashMap<>();

  public AppInfo(DexApplication application) {
    this.app = application;
    this.dexItemFactory = app.dexItemFactory;
  }

  protected AppInfo(AppInfo previous) {
    this.app = previous.app;
    this.dexItemFactory = app.dexItemFactory;
    this.definitions.putAll(previous.definitions);
  }

  protected AppInfo(AppInfo previous, GraphLense lense) {
    // Do not rewrite basic structure, as the type information in the lense is about applied uses
    // and not definitions.
    this(previous);
  }

  private Map<Descriptor, KeyedDexItem> computeDefinitions(DexType type) {
    Builder<Descriptor, KeyedDexItem> builder = ImmutableMap.builder();
    DexClass clazz = app.definitionFor(type);
    if (clazz != null) {
      clazz.forEachMethod(method -> builder.put(method.getKey(), method));
      clazz.forEachField(field -> builder.put(field.getKey(), field));
    }
    return builder.build();
  }

  public Iterable<DexProgramClass> classes() {
    return app.classes();
  }

  public Iterable<DexLibraryClass> libraryClasses() {
    return app.libraryClasses();
  }

  public DexClass definitionFor(DexType type) {
    return app.definitionFor(type);
  }

  public DexEncodedMethod definitionFor(DexMethod method) {
    return (DexEncodedMethod) getDefinitions(method.getHolder()).get(method);
  }

  public DexEncodedField definitionFor(DexField field) {
    return (DexEncodedField) getDefinitions(field.getHolder()).get(field);
  }

  private Map<Descriptor, KeyedDexItem> getDefinitions(DexType type) {
    Map<Descriptor, KeyedDexItem> typeDefinitions = definitions.get(type);
    if (typeDefinitions != null) {
      return typeDefinitions;
    }

    typeDefinitions = computeDefinitions(type);
    Map<Descriptor, KeyedDexItem> existing = definitions.putIfAbsent(type, typeDefinitions);
    return existing != null ? existing : typeDefinitions;
  }

  private DexEncodedMethod lookupDirectStaticOrConstructorTarget(DexMethod method) {
    assert method.holder.isClassType();
    return lookupTargetAlongSuperChain(method.holder, method, DexClass::findDirectTarget);
  }

  /**
   * Lookup static method following the super chain from the holder of {@code method}.
   * <p>
   * This method will lookup only static methods.
   *
   * @param method the method to lookup
   * @return The actual target for {@code method} or {@code null} if none found.
   */
  public DexEncodedMethod lookupStaticTarget(DexMethod method) {
    DexEncodedMethod target = lookupDirectStaticOrConstructorTarget(method);
    return target == null || target.accessFlags.isStatic() ? target : null;
  }

  /**
   * Lookup direct method following the super chain from the holder of {@code method}.
   * <p>
   * This method will lookup private and constructor methods.
   *
   * @param method the method to lookup
   * @return The actual target for {@code method} or {@code null} if none found.
   */
  public DexEncodedMethod lookupDirectTarget(DexMethod method) {
    DexEncodedMethod target = lookupDirectStaticOrConstructorTarget(method);
    return target == null || !target.accessFlags.isStatic() ? target : null;
  }

  /**
   * Lookup virtual method starting in type and following the super chain.
   * <p>
   * If the target cannot be found along the super-chain, look for a default implementation in one
   * of the interfaces.
   */
  public DexEncodedMethod lookupVirtualTarget(DexType type, DexMethod method) {
    assert type.isClassType();
    DexEncodedMethod result
        = lookupTargetAlongSuperChain(type, method, DexClass::findVirtualTarget);
    if (result != null) {
      return result;
    }
    return lookupTargetAlongInterfaceChain(type, method,
        (dexClass, dexMethod) -> {
          DexEncodedMethod virtualTarget = dexClass.findVirtualTarget(dexMethod);
          return virtualTarget != null && virtualTarget.getCode() != null
              ? virtualTarget
              : null;
        });
  }

  /**
   * Lookup virtual method starting in type and following the super chain.
   * <p>
   * If the target cannot be found along the super-chain, look for a definition in one of
   * the interfaces.
   */
  public DexEncodedMethod lookupVirtualDefinition(DexType type, DexMethod method) {
    assert type.isClassType();
    DexEncodedMethod result
        = lookupTargetAlongSuperChain(type, method, DexClass::findVirtualTarget);
    if (result != null) {
      return result;
    }
    return lookupTargetAlongInterfaceChain(type, method, DexClass::findVirtualTarget);
  }

  /**
   * Lookup instance field starting in type and following the super chain.
   */
  public DexEncodedField lookupInstanceTarget(DexType type, DexField field) {
    assert type.isClassType();
    return lookupTargetAlongSuperChain(type, field, DexClass::findInstanceTarget);
  }

  /**
   * Lookup static field starting in type and following the super chain.
   */
  public DexEncodedField lookupStaticTarget(DexType type, DexField field) {
    assert type.isClassType();
    DexEncodedField target = lookupTargetAlongSuperChain(type, field, DexClass::findStaticTarget);
    if (target == null) {
      target = lookupTargetAlongInterfaceChain(type, field, DexClass::findStaticTarget);
    }
    return target;
  }

  /**
   * Traverse along the super chain until lookup returns non-null value.
   */
  private <S extends DexItem, T extends Descriptor<S, T>> S lookupTargetAlongSuperChain(
      DexType type,
      T desc,
      BiFunction<DexClass, T, S> lookup) {
    assert type != null;
    DexClass holder = definitionFor(type);
    while (holder != null) {
      S result = lookup.apply(holder, desc);
      if (result != null) {
        return result;
      }
      if (holder.superType == null) {
        return null;
      }
      holder = definitionFor(holder.superType);
    }
    return null;
  }

  /**
   * Traverse along the super chain and the interface chains until lookup returns non-null value.
   */
  private <S extends DexItem, T extends Descriptor<S, T>> S lookupTargetAlongSuperAndInterfaceChain(
      DexType type,
      T desc,
      BiFunction<DexClass, T, S> lookup) {
    DexClass holder = definitionFor(type);
    if (holder == null) {
      return null;
    }
    S result = lookup.apply(holder, desc);
    if (result != null) {
      return result;
    }
    if (holder.superType != null) {
      result = lookupTargetAlongSuperAndInterfaceChain(holder.superType, desc, lookup);
      if (result != null) {
        return result;
      }
    }
    for (DexType iface : holder.interfaces.values) {
      result = lookupTargetAlongSuperAndInterfaceChain(iface, desc, lookup);
      if (result != null) {
        return result;
      }
    }
    return null;
  }

  private boolean isDefaultMethod(DexItem dexItem) {
    return dexItem != null && dexItem instanceof DexEncodedMethod &&
        !((DexEncodedMethod) dexItem).accessFlags.isStatic() &&
        ((DexEncodedMethod) dexItem).getCode() != null;
  }

  /** Returns if <code>interface1</code> is a super interface of <code>interface2</code> */
  private boolean isSuperInterfaceOf(DexType interface1, DexType interface2) {
    assert definitionFor(interface1).isInterface();
    DexClass holder = definitionFor(interface2);
    assert holder.isInterface();
    for (DexType iface : holder.interfaces.values) {
      if (iface == interface1 || isSuperInterfaceOf(interface1, iface)) {
        return true;
      }
    }
    return false;
  }

  private <S extends DexItem> S resolveAmbiguousResult(S previousResult, S newResult) {
    // For default methods return the item found lowest in the interface hierarchy. Different
    // implementations can come from different paths in a diamond.
    // See §9.4.1 in The Java® Language Specification, Java SE 8 Edition.
    if (previousResult != null
        && previousResult != newResult
        && isDefaultMethod(previousResult)
        && isDefaultMethod(newResult)) {
      DexEncodedMethod previousMethod = (DexEncodedMethod) previousResult;
      DexEncodedMethod newMethod = (DexEncodedMethod) newResult;
      if (isSuperInterfaceOf(previousMethod.method.getHolder(), newMethod.method.getHolder())) {
        return newResult;
      }
      if (isSuperInterfaceOf(newMethod.method.getHolder(), previousMethod.method.getHolder())) {
        return previousResult;
      }
      throw new CompilationError("Duplicate default methods named "
          + previousResult.toSourceString()
          + " are inherited from the types "
          + previousMethod.method.holder.getName()
          + " and "
          + newMethod.method.holder.getName());
    } else {
      // Return the first item found for everything except default methods.
      return previousResult != null ? previousResult : newResult;
    }
  }

  /**
   * Traverse along the interface chains until lookup returns non-null value.
   */
  private <S extends DexItem, T extends Descriptor<S, T>> S lookupTargetAlongInterfaceChain(
      DexType type,
      T desc,
      BiFunction<DexClass, T, S> lookup) {
    DexClass holder = definitionFor(type);
    if (holder == null) {
      // TODO(herhut): The subtype hierarchy is broken. Handle this case.
      return null;
    }
    S result = null;
    for (DexType iface : holder.interfaces.values) {
      S localResult = lookupTargetAlongSuperAndInterfaceChain(iface, desc, lookup);
      if (localResult != null) {
        result = resolveAmbiguousResult(result, localResult);
      }
    }
    if (holder.superType != null) {
      S localResult = lookupTargetAlongInterfaceChain(holder.superType, desc, lookup);
      if (localResult != null) {
        result = resolveAmbiguousResult(result, localResult);
      }
    }
    return result;
  }

  public DexEncodedMethod lookup(Type type, DexMethod target) {
    DexEncodedMethod definition;
    DexType holder = target.getHolder();
    if (!holder.isClassType()) {
      return null;
    }
    if (type == Type.VIRTUAL || type == Type.INTERFACE) {
      definition = lookupVirtualDefinition(holder, target);
    } else if (type == Type.DIRECT) {
      definition = lookupDirectTarget(target);
    } else if (type == Type.STATIC) {
      definition = lookupStaticTarget(target);
    } else if (type == Type.SUPER) {
      definition = lookupVirtualTarget(holder, target);
    } else {
      return null;
    }
    return definition;
  }

  public boolean hasSubtyping() {
    return false;
  }

  public AppInfoWithSubtyping withSubtyping() {
    return null;
  }

  public boolean hasLiveness() {
    return false;
  }

  public AppInfoWithLiveness withLiveness() {
    return null;
  }

  public void registerNewType(DexType newType, DexType superType) {
    // We do not track subtyping relationships in the basic AppInfo. So do nothing.
  }

  public List<DexClass> getSuperTypeClasses(DexType type) {
    List<DexClass> result = new ArrayList<>();
    do {
      DexClass clazz = definitionFor(type);
      if (clazz == null) {
        break;
      }
      result.add(clazz);
      type = clazz.superType;
    } while (type != null);
    return result;
  }
}
