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

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.KeepFieldInfo.Joiner;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

// Non-mutable collection of keep information pertaining to a program.
public abstract class KeepInfoCollection {

  // TODO(b/157538235): This should not be bottom.
  private static KeepClassInfo keepInfoForNonProgramClass() {
    return KeepClassInfo.bottom();
  }

  // TODO(b/157538235): This should not be bottom.
  private static KeepMethodInfo keepInfoForNonProgramMethod() {
    return KeepMethodInfo.bottom();
  }

  // TODO(b/157538235): This should not be bottom.
  private static KeepFieldInfo keepInfoForNonProgramField() {
    return KeepFieldInfo.bottom();
  }

  abstract Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> getRuleInstances();

  /**
   * Base accessor for keep info on a class.
   *
   * <p>Access may never be granted directly on DexType as the "keep info" for any non-program type
   * is not the same as the default keep info for a program type. By typing the interface at program
   * item we can eliminate errors where a reference to a non-program item results in optimizations
   * assuming aspects of it can be changed when in fact they can not.
   */
  public abstract KeepClassInfo getClassInfo(DexProgramClass clazz);

  /**
   * Base accessor for keep info on a method.
   *
   * <p>See comment on class access for why this is typed at program method.
   */
  public abstract KeepMethodInfo getMethodInfo(DexEncodedMethod method, DexProgramClass holder);

  /**
   * Base accessor for keep info on a field.
   *
   * <p>See comment on class access for why this is typed at program field.
   */
  public abstract KeepFieldInfo getFieldInfo(DexEncodedField field, DexProgramClass holder);

  public final KeepClassInfo getClassInfo(DexType type, DexDefinitionSupplier definitions) {
    DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(type));
    return clazz == null ? keepInfoForNonProgramClass() : getClassInfo(clazz);
  }

  public final KeepMethodInfo getMethodInfo(ProgramMethod method) {
    return getMethodInfo(method.getDefinition(), method.getHolder());
  }

  public final KeepMethodInfo getMethodInfo(DexMethod method, DexDefinitionSupplier definitions) {
    DexProgramClass holder = asProgramClassOrNull(definitions.definitionFor(method.holder));
    if (holder == null) {
      return keepInfoForNonProgramMethod();
    }
    DexEncodedMethod definition = holder.lookupMethod(method);
    return definition == null ? KeepMethodInfo.bottom() : getMethodInfo(definition, holder);
  }

  public final KeepFieldInfo getFieldInfo(ProgramField field) {
    return getFieldInfo(field.getDefinition(), field.getHolder());
  }

  public final KeepFieldInfo getFieldInfo(DexField field, DexDefinitionSupplier definitions) {
    DexProgramClass holder = asProgramClassOrNull(definitions.definitionFor(field.holder));
    if (holder == null) {
      return keepInfoForNonProgramField();
    }
    DexEncodedField definition = holder.lookupField(field);
    return definition == null ? KeepFieldInfo.bottom() : getFieldInfo(definition, holder);
  }

  public final KeepInfo getInfo(DexReference reference, DexDefinitionSupplier definitions) {
    if (reference.isDexType()) {
      return getClassInfo(reference.asDexType(), definitions);
    }
    if (reference.isDexMethod()) {
      return getMethodInfo(reference.asDexMethod(), definitions);
    }
    if (reference.isDexField()) {
      return getFieldInfo(reference.asDexField(), definitions);
    }
    throw new Unreachable();
  }

  public final boolean isPinned(DexReference reference, DexDefinitionSupplier definitions) {
    return getInfo(reference, definitions).isPinned();
  }

  public final boolean isPinned(DexType type, DexDefinitionSupplier definitions) {
    return getClassInfo(type, definitions).isPinned();
  }

  public final boolean isPinned(DexMethod method, DexDefinitionSupplier definitions) {
    return getMethodInfo(method, definitions).isPinned();
  }

  public final boolean isPinned(DexField field, DexDefinitionSupplier definitions) {
    return getFieldInfo(field, definitions).isPinned();
  }

  public final boolean isMinificationAllowed(
      DexReference reference,
      DexDefinitionSupplier definitions,
      GlobalKeepInfoConfiguration configuration) {
    return configuration.isMinificationEnabled()
        && getInfo(reference, definitions).isMinificationAllowed(configuration);
  }

  public final boolean verifyNoneArePinned(Collection<DexType> types, AppInfo appInfo) {
    for (DexType type : types) {
      DexProgramClass clazz =
          asProgramClassOrNull(appInfo.definitionForWithoutExistenceAssert(type));
      assert clazz == null || !getClassInfo(clazz).isPinned();
    }
    return true;
  }

  // TODO(b/156715504): We should try to avoid the need for iterating pinned items.
  @Deprecated
  public abstract void forEachPinnedType(Consumer<DexType> consumer);

  // TODO(b/156715504): We should try to avoid the need for iterating pinned items.
  @Deprecated
  public abstract void forEachPinnedMethod(Consumer<DexMethod> consumer);

  // TODO(b/156715504): We should try to avoid the need for iterating pinned items.
  @Deprecated
  public abstract void forEachPinnedField(Consumer<DexField> consumer);

  public abstract KeepInfoCollection rewrite(NestedGraphLens lens);

  public abstract KeepInfoCollection mutate(Consumer<MutableKeepInfoCollection> mutator);

  // Mutation interface for building up the keep info.
  public static class MutableKeepInfoCollection extends KeepInfoCollection {

    // These are typed at signatures but the interface should make sure never to allow access
    // directly with a signature. See the comment in KeepInfoCollection.
    private final Map<DexType, KeepClassInfo> keepClassInfo;
    private final Map<DexMethod, KeepMethodInfo> keepMethodInfo;
    private final Map<DexField, KeepFieldInfo> keepFieldInfo;

    // Map of applied rules for which keys may need to be mutated.
    private final Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> ruleInstances;

    MutableKeepInfoCollection() {
      this(
          new IdentityHashMap<>(),
          new IdentityHashMap<>(),
          new IdentityHashMap<>(),
          new IdentityHashMap<>());
    }

    private MutableKeepInfoCollection(
        Map<DexType, KeepClassInfo> keepClassInfo,
        Map<DexMethod, KeepMethodInfo> keepMethodInfo,
        Map<DexField, KeepFieldInfo> keepFieldInfo,
        Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> ruleInstances) {
      this.keepClassInfo = keepClassInfo;
      this.keepMethodInfo = keepMethodInfo;
      this.keepFieldInfo = keepFieldInfo;
      this.ruleInstances = ruleInstances;
    }

    @Override
    public KeepInfoCollection rewrite(NestedGraphLens lens) {
      Map<DexType, KeepClassInfo> newClassInfo = new IdentityHashMap<>(keepClassInfo.size());
      keepClassInfo.forEach(
          (type, info) -> {
            DexType newType = lens.lookupType(type);
            assert !info.isPinned() || type == newType;
            newClassInfo.put(newType, info);
          });
      Map<DexMethod, KeepMethodInfo> newMethodInfo = new IdentityHashMap<>(keepMethodInfo.size());
      keepMethodInfo.forEach(
          (method, info) -> {
            DexMethod newMethod = lens.getRenamedMethodSignature(method);
            assert !info.isPinned() || method == newMethod;
            newMethodInfo.put(newMethod, info);
          });
      Map<DexField, KeepFieldInfo> newFieldInfo = new IdentityHashMap<>(keepFieldInfo.size());
      keepFieldInfo.forEach(
          (field, info) -> {
            DexField newField = lens.getRenamedFieldSignature(field);
            assert !info.isPinned() || field == newField;
            newFieldInfo.put(newField, info);
          });
      Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> newRuleInstances =
          new IdentityHashMap<>(ruleInstances.size());
      ruleInstances.forEach(
          (reference, consumers) -> {
            DexReference newReference;
            if (reference.isDexType()) {
              DexType newType = lens.lookupType(reference.asDexType());
              if (!newType.isClassType()) {
                assert newType.isIntType() : "Expected only enum unboxing type changes.";
                return;
              }
              newReference = newType;
            } else if (reference.isDexMethod()) {
              newReference = lens.getRenamedMethodSignature(reference.asDexMethod());
            } else {
              assert reference.isDexField();
              newReference = lens.getRenamedFieldSignature(reference.asDexField());
            }
            newRuleInstances.put(newReference, consumers);
          });
      return new MutableKeepInfoCollection(
          newClassInfo, newMethodInfo, newFieldInfo, newRuleInstances);
    }

    @Override
    Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> getRuleInstances() {
      return ruleInstances;
    }

    void evaluateRule(
        DexReference reference,
        DexDefinitionSupplier definitions,
        Consumer<KeepInfo.Joiner<?, ?, ?>> fn) {
      joinInfo(reference, definitions, fn);
      if (!getInfo(reference, definitions).isBottom()) {
        ruleInstances.computeIfAbsent(reference, k -> new ArrayList<>()).add(fn);
      }
    }

    @Override
    public KeepClassInfo getClassInfo(DexProgramClass clazz) {
      return keepClassInfo.getOrDefault(clazz.type, KeepClassInfo.bottom());
    }

    @Override
    public KeepMethodInfo getMethodInfo(DexEncodedMethod method, DexProgramClass holder) {
      assert method.holder() == holder.type;
      return keepMethodInfo.getOrDefault(method.method, KeepMethodInfo.bottom());
    }

    @Override
    public KeepFieldInfo getFieldInfo(DexEncodedField field, DexProgramClass holder) {
      assert field.holder() == holder.type;
      return keepFieldInfo.getOrDefault(field.field, KeepFieldInfo.bottom());
    }

    public void joinClass(DexProgramClass clazz, Consumer<KeepClassInfo.Joiner> fn) {
      KeepClassInfo info = getClassInfo(clazz);
      if (info.isTop()) {
        return;
      }
      KeepClassInfo.Joiner joiner = info.joiner();
      fn.accept(joiner);
      KeepClassInfo joined = joiner.join();
      if (!info.equals(joined)) {
        keepClassInfo.put(clazz.type, joined);
      }
    }

    public void joinInfo(
        DexReference reference,
        DexDefinitionSupplier definitions,
        Consumer<KeepInfo.Joiner<?, ?, ?>> fn) {
      if (reference.isDexType()) {
        DexType type = reference.asDexType();
        DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(type));
        if (clazz != null) {
          joinClass(clazz, fn::accept);
        }
      } else if (reference.isDexMethod()) {
        DexMethod method = reference.asDexMethod();
        DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(method.holder));
        DexEncodedMethod definition = method.lookupOnClass(clazz);
        if (definition != null) {
          joinMethod(clazz, definition, fn::accept);
        }
      } else {
        assert reference.isDexField();
        DexField field = reference.asDexField();
        DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(field.holder));
        DexEncodedField definition = field.lookupOnClass(clazz);
        if (definition != null) {
          joinField(clazz, definition, fn::accept);
        }
      }
    }

    public void keepClass(DexProgramClass clazz) {
      joinClass(clazz, KeepInfo.Joiner::top);
    }

    public void pinClass(DexProgramClass clazz) {
      joinClass(clazz, KeepInfo.Joiner::pin);
    }

    public void joinMethod(
        DexProgramClass holder, DexEncodedMethod method, Consumer<KeepMethodInfo.Joiner> fn) {
      KeepMethodInfo info = getMethodInfo(method, holder);
      if (info == KeepMethodInfo.top()) {
        return;
      }
      KeepMethodInfo.Joiner joiner = info.joiner();
      fn.accept(joiner);
      KeepMethodInfo joined = joiner.join();
      if (!info.equals(joined)) {
        keepMethodInfo.put(method.method, joined);
      }
    }

    public void joinMethod(ProgramMethod programMethod, Consumer<KeepMethodInfo.Joiner> fn) {
      joinMethod(programMethod.getHolder(), programMethod.getDefinition(), fn);
    }

    public void keepMethod(ProgramMethod programMethod) {
      keepMethod(programMethod.getHolder(), programMethod.getDefinition());
    }

    public void keepMethod(DexProgramClass holder, DexEncodedMethod method) {
      joinMethod(holder, method, KeepInfo.Joiner::top);
    }

    public void pinMethod(DexProgramClass holder, DexEncodedMethod method) {
      joinMethod(holder, method, KeepInfo.Joiner::pin);
    }

    // Unpinning a method represents a non-monotonic change to the keep info of that item.
    // This is generally unsound as it requires additional analysis to determine that a method that
    // was pinned no longer is. A known sound example is the enum analysis that will identify
    // non-escaping enums on enum types that are not pinned, thus their methods do not need to be
    // retained even if a rule has marked them as conditionally pinned.
    public void unsafeUnpinMethod(ProgramMethod method) {
      // This asserts that the holder is not pinned as some analysis must have established that the
      // type is not "present" and thus the method need not be pinned.
      assert !getClassInfo(method.getHolder()).isPinned();
      unsafeUnpinMethod(method.getReference());
    }

    // TODO(b/157700141): Avoid pinning/unpinning references.
    @Deprecated
    public void unsafeUnpinMethod(DexMethod method) {
      KeepMethodInfo info = keepMethodInfo.get(method);
      if (info != null && info.isPinned()) {
        keepMethodInfo.put(method, info.builder().unpin().build());
      }
    }

    public void joinField(
        DexProgramClass holder, DexEncodedField field, Consumer<KeepFieldInfo.Joiner> fn) {
      KeepFieldInfo info = getFieldInfo(field, holder);
      if (info.isTop()) {
        return;
      }
      Joiner joiner = info.joiner();
      fn.accept(joiner);
      KeepFieldInfo joined = joiner.join();
      if (!info.equals(joined)) {
        keepFieldInfo.put(field.field, joined);
      }
    }

    public void keepField(ProgramField programField) {
      keepField(programField.getHolder(), programField.getDefinition());
    }

    public void keepField(DexProgramClass holder, DexEncodedField field) {
      joinField(holder, field, KeepInfo.Joiner::top);
    }

    public void pinField(DexProgramClass holder, DexEncodedField field) {
      joinField(holder, field, KeepInfo.Joiner::pin);
    }

    public void keepMember(DexProgramClass holder, DexEncodedMember<?, ?> member) {
      if (member.isDexEncodedMethod()) {
        keepMethod(holder, member.asDexEncodedMethod());
      } else {
        assert member.isDexEncodedField();
        keepField(holder, member.asDexEncodedField());
      }
    }

    public void unsafeUnpinField(DexProgramClass holder, DexEncodedField field) {
      assert holder.type == field.holder();
      assert !getClassInfo(holder).isPinned();
      KeepFieldInfo info = this.keepFieldInfo.get(field.toReference());
      if (info != null && info.isPinned()) {
        keepFieldInfo.put(field.toReference(), info.builder().unpin().build());
      }
    }

    @Override
    public KeepInfoCollection mutate(Consumer<MutableKeepInfoCollection> mutator) {
      mutator.accept(this);
      return this;
    }

    @Override
    public void forEachPinnedType(Consumer<DexType> consumer) {
      keepClassInfo.forEach(
          (type, info) -> {
            if (info.isPinned()) {
              consumer.accept(type);
            }
          });
    }

    @Override
    public void forEachPinnedMethod(Consumer<DexMethod> consumer) {
      keepMethodInfo.forEach(
          (method, info) -> {
            if (info.isPinned()) {
              consumer.accept(method);
            }
          });
    }

    @Override
    public void forEachPinnedField(Consumer<DexField> consumer) {
      keepFieldInfo.forEach(
          (field, info) -> {
            if (info.isPinned()) {
              consumer.accept(field);
            }
          });
    }
  }
}
