// 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.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AppInfo implements DexDefinitionSupplier {

  private final DexApplication app;
  private final DexItemFactory dexItemFactory;

  // For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
  // class being optimized.
  private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses;

  // Set when a new AppInfo replaces a previous one. All public methods should verify that the
  // current instance is not obsolete, to ensure that we almost use the most recent AppInfo.
  private final BooleanBox obsolete;

  public AppInfo(DexApplication application) {
    this(application, new ConcurrentHashMap<>(), new BooleanBox());
  }

  // For desugaring.
  protected AppInfo(AppInfo appInfo) {
    this(appInfo.app, appInfo.synthesizedClasses, appInfo.obsolete);
  }

  // For AppInfoWithLiveness.
  protected AppInfo(AppInfoWithClassHierarchy previous) {
    this(
        ((AppInfo) previous).app,
        new ConcurrentHashMap<>(((AppInfo) previous).synthesizedClasses),
        new BooleanBox());
  }

  private AppInfo(
      DexApplication application,
      ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses,
      BooleanBox obsolete) {
    this.app = application;
    this.dexItemFactory = application.dexItemFactory;
    this.synthesizedClasses = synthesizedClasses;
    this.obsolete = obsolete;
  }

  protected InternalOptions options() {
    return app.options;
  }

  public void copyMetadataFromPrevious(AppInfo previous) {
    this.synthesizedClasses.putAll(previous.synthesizedClasses);
  }

  public boolean isObsolete() {
    return obsolete.get();
  }

  public void markObsolete() {
    obsolete.set();
  }

  public void unsetObsolete() {
    obsolete.unset();
  }

  public boolean checkIfObsolete() {
    assert !isObsolete();
    return true;
  }

  public DexApplication app() {
    assert checkIfObsolete();
    return app;
  }

  @Override
  public DexItemFactory dexItemFactory() {
    assert checkIfObsolete();
    return dexItemFactory;
  }

  public void addSynthesizedClass(DexProgramClass clazz) {
    assert checkIfObsolete();
    assert clazz.type.isD8R8SynthesizedClassType();
    DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
    assert previous == null || previous == clazz;
  }

  public Collection<DexProgramClass> synthesizedClasses() {
    assert checkIfObsolete();
    return Collections.unmodifiableCollection(synthesizedClasses.values());
  }

  private Map<DexField, DexEncodedField> computeFieldDefinitions(DexType type) {
    Builder<DexField, DexEncodedField> builder = ImmutableMap.builder();
    DexClass clazz = definitionFor(type);
    if (clazz != null) {
      clazz.forEachField(field -> builder.put(field.field, field));
    }
    return builder.build();
  }

  public Collection<DexProgramClass> classes() {
    assert checkIfObsolete();
    return app.classes();
  }

  public Iterable<DexProgramClass> classesWithDeterministicOrder() {
    assert checkIfObsolete();
    return app.classesWithDeterministicOrder();
  }

  @Override
  public DexClass definitionFor(DexType type) {
    return definitionForWithoutExistenceAssert(type);
  }

  public final DexClass definitionForWithoutExistenceAssert(DexType type) {
    assert checkIfObsolete();
    DexProgramClass cached = synthesizedClasses.get(type);
    if (cached != null) {
      assert app.definitionFor(type) == null;
      return cached;
    }
    return app.definitionFor(type);
  }

  public DexClass definitionForDesugarDependency(DexClass dependent, DexType type) {
    if (dependent.type == type) {
      return dependent;
    }
    DexClass definition = definitionFor(type);
    if (definition != null && !definition.isLibraryClass() && dependent.isProgramClass()) {
      InterfaceMethodRewriter.reportDependencyEdge(
          dependent.asProgramClass(), definition, options());
    }
    return definition;
  }

  public DexProgramClass unsafeDirectProgramTypeLookup(DexType type) {
    return app.programDefinitionFor(type);
  }

  public Origin originFor(DexType type) {
    assert checkIfObsolete();
    DexClass definition = app.definitionFor(type);
    return definition == null ? Origin.unknown() : definition.origin;
  }

  /**
   * Lookup static method on the method holder, or answers null.
   *
   * @param method the method to lookup
   * @param context the method the invoke is contained in, i.e., the caller.
   * @return The actual target for {@code method} if on the holder, or {@code null}.
   */
  public final DexEncodedMethod lookupStaticTargetOnItself(
      DexMethod method, ProgramMethod context) {
    if (method.holder != context.getHolderType()) {
      return null;
    }
    DexEncodedMethod singleTarget = context.getHolder().lookupDirectMethod(method);
    if (singleTarget != null && singleTarget.isStatic()) {
      return singleTarget;
    }
    return null;
  }

  /**
   * Lookup direct method on the method holder, or answers null.
   *
   * @param method the method to lookup
   * @param context the method the invoke is contained in, i.e., the caller.
   * @return The actual target for {@code method} if on the holder, or {@code null}.
   */
  public final DexEncodedMethod lookupDirectTargetOnItself(
      DexMethod method, ProgramMethod context) {
    if (method.holder != context.getHolderType()) {
      return null;
    }
    DexEncodedMethod singleTarget = context.getHolder().lookupDirectMethod(method);
    if (singleTarget != null && !singleTarget.isStatic()) {
      return singleTarget;
    }
    return null;
  }

  public boolean hasClassHierarchy() {
    assert checkIfObsolete();
    return false;
  }

  public AppInfoWithClassHierarchy withClassHierarchy() {
    assert checkIfObsolete();
    return null;
  }

  public boolean hasLiveness() {
    assert checkIfObsolete();
    return false;
  }

  public AppInfoWithLiveness withLiveness() {
    assert checkIfObsolete();
    return null;
  }

  public boolean isInMainDexList(DexType type) {
    assert checkIfObsolete();
    return app.mainDexList.contains(type);
  }

  public final FieldResolutionResult resolveField(DexField field, ProgramMethod context) {
    return resolveFieldOn(field.holder, field, context);
  }

  public FieldResolutionResult resolveFieldOn(DexType type, DexField field, ProgramMethod context) {
    // Only allow resolution if the field is declared in the context.
    if (type != context.getHolderType()) {
      return FieldResolutionResult.failure();
    }
    DexProgramClass clazz = context.getHolder();
    DexEncodedField definition = clazz.lookupField(field);
    return definition != null
        ? new SuccessfulFieldResolutionResult(clazz, clazz, definition)
        : FieldResolutionResult.unknown();
  }
}
