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

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * For a concrete field, stores the contexts in which the field is accessed.
 *
 * <p>If the concrete field does not have any accesses, then {@link EmptyAccessContexts}.
 *
 * <p>If nothing is nothing about the accesses to the concrete field, then {@link
 * UnknownAccessContexts}.
 *
 * <p>Otherwise, the concrete contexts in which the field is accessed is maintained by {@link
 * ConcreteAccessContexts}. The access contexts are qualified by the field reference they access.
 *
 * <p>Example: If a field `int Foo.field` is accessed directly in `void Main.direct()` and
 * indirectly via a non-rebound reference `int FooSub.field` in `void Main.indirect()`, then the
 * collection is:
 *
 * <pre>
 *   ConcreteAccessContexts {
 *     `int Foo.field` -> { `void Main.direct()` }
 *     `int FooSub.field` -> { `void Main.indirect()` }
 *   }
 * </pre>
 */
public abstract class AbstractAccessContexts {

  abstract void flattenAccessContexts(DexField field);

  abstract void forEachAccessContext(Consumer<ProgramMethod> consumer);

  /**
   * Returns true if this field is written by a method for which {@param predicate} returns true.
   */
  abstract boolean isAccessedInMethodSatisfying(Predicate<ProgramMethod> predicate);

  /**
   * Returns true if this field is only written by methods for which {@param predicate} returns
   * true.
   */
  abstract boolean isAccessedOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate);

  /**
   * Returns true if this field is written by a method in the program other than {@param method}.
   */
  abstract boolean isAccessedOutside(DexEncodedMethod method);

  abstract int getNumberOfAccessContexts();

  public boolean isBottom() {
    return false;
  }

  public boolean isConcrete() {
    return false;
  }

  abstract boolean isEmpty();

  public ConcreteAccessContexts asConcrete() {
    return null;
  }

  public boolean isTop() {
    return false;
  }

  abstract AbstractAccessContexts rewrittenWithLens(
      DexDefinitionSupplier definitions, GraphLens lens);

  public static EmptyAccessContexts empty() {
    return EmptyAccessContexts.getInstance();
  }

  public static UnknownAccessContexts unknown() {
    return UnknownAccessContexts.getInstance();
  }

  public static class EmptyAccessContexts extends AbstractAccessContexts {

    public static EmptyAccessContexts INSTANCE = new EmptyAccessContexts();

    private EmptyAccessContexts() {}

    public static EmptyAccessContexts getInstance() {
      return INSTANCE;
    }

    @Override
    void flattenAccessContexts(DexField field) {
      // Intentionally empty.
    }

    @Override
    void forEachAccessContext(Consumer<ProgramMethod> consumer) {
      // Intentionally empty.
    }

    @Override
    boolean isAccessedInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      return false;
    }

    @Override
    boolean isAccessedOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      return true;
    }

    @Override
    boolean isAccessedOutside(DexEncodedMethod method) {
      return false;
    }

    @Override
    int getNumberOfAccessContexts() {
      return 0;
    }

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

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

    @Override
    AbstractAccessContexts rewrittenWithLens(DexDefinitionSupplier definitions, GraphLens lens) {
      return this;
    }
  }

  public static class ConcreteAccessContexts extends AbstractAccessContexts {

    private final Map<DexField, ProgramMethodSet> accessesWithContexts;

    public ConcreteAccessContexts() {
      this(new IdentityHashMap<>());
    }

    public ConcreteAccessContexts(Map<DexField, ProgramMethodSet> accessesWithContexts) {
      this.accessesWithContexts = accessesWithContexts;
    }

    void forEachAccess(Consumer<DexField> consumer, Predicate<DexField> predicate) {
      if (accessesWithContexts != null) {
        accessesWithContexts.forEach(
            (access, contexts) -> {
              if (predicate.test(access)) {
                consumer.accept(access);
              }
            });
      }
    }

    @Override
    void forEachAccessContext(Consumer<ProgramMethod> consumer) {
      // There can be indirect reads and writes of the same field reference, so we need to keep
      // track
      // of the previously-seen indirect accesses to avoid reporting duplicates.
      ProgramMethodSet visited = ProgramMethodSet.create();
      if (accessesWithContexts != null) {
        for (ProgramMethodSet encodedAccessContexts : accessesWithContexts.values()) {
          for (ProgramMethod encodedAccessContext : encodedAccessContexts) {
            if (visited.add(encodedAccessContext)) {
              consumer.accept(encodedAccessContext);
            }
          }
        }
      }
    }

    public Map<DexField, ProgramMethodSet> getAccessesWithContexts() {
      return accessesWithContexts;
    }

    @Override
    int getNumberOfAccessContexts() {
      if (accessesWithContexts.size() == 1) {
        return accessesWithContexts.values().iterator().next().size();
      }
      throw new Unreachable(
          "Should only be querying the number of access contexts after flattening");
    }

    ProgramMethod getUniqueAccessContext() {
      if (accessesWithContexts != null && accessesWithContexts.size() == 1) {
        ProgramMethodSet contexts = accessesWithContexts.values().iterator().next();
        if (contexts.size() == 1) {
          return contexts.iterator().next();
        }
      }
      return null;
    }

    @Override
    void flattenAccessContexts(DexField field) {
      if (accessesWithContexts != null) {
        ProgramMethodSet flattenedAccessContexts =
            accessesWithContexts.computeIfAbsent(field, ignore -> ProgramMethodSet.create());
        accessesWithContexts.forEach(
            (access, contexts) -> {
              if (access != field) {
                flattenedAccessContexts.addAll(contexts);
              }
            });
        accessesWithContexts.clear();
        if (!flattenedAccessContexts.isEmpty()) {
          accessesWithContexts.put(field, flattenedAccessContexts);
        }
        assert accessesWithContexts.size() <= 1;
      }
    }

    /**
     * Returns true if this field is written by a method for which {@param predicate} returns true.
     */
    @Override
    public boolean isAccessedInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      for (ProgramMethodSet encodedWriteContexts : accessesWithContexts.values()) {
        for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
          if (predicate.test(encodedWriteContext)) {
            return true;
          }
        }
      }
      return false;
    }

    /**
     * Returns true if this field is only written by methods for which {@param predicate} returns
     * true.
     */
    @Override
    public boolean isAccessedOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      for (ProgramMethodSet encodedWriteContexts : accessesWithContexts.values()) {
        for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
          if (!predicate.test(encodedWriteContext)) {
            return false;
          }
        }
      }
      return true;
    }

    /**
     * Returns true if this field is written by a method in the program other than {@param method}.
     */
    @Override
    public boolean isAccessedOutside(DexEncodedMethod method) {
      for (ProgramMethodSet encodedWriteContexts : accessesWithContexts.values()) {
        for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
          if (encodedWriteContext.getDefinition() != method) {
            return true;
          }
        }
      }
      return false;
    }

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

    @Override
    public ConcreteAccessContexts asConcrete() {
      return this;
    }

    @Override
    public boolean isEmpty() {
      return accessesWithContexts.isEmpty();
    }

    boolean recordAccess(DexField access, ProgramMethod context) {
      return accessesWithContexts
          .computeIfAbsent(access, ignore -> ProgramMethodSet.create())
          .add(context);
    }

    @Override
    ConcreteAccessContexts rewrittenWithLens(DexDefinitionSupplier definitions, GraphLens lens) {
      Map<DexField, ProgramMethodSet> newAccessesWithContexts = new IdentityHashMap<>();
      accessesWithContexts.forEach(
          (access, contexts) -> {
            ProgramMethodSet newContexts =
                newAccessesWithContexts.computeIfAbsent(
                    lens.lookupField(access), ignore -> ProgramMethodSet.create());
            for (ProgramMethod context : contexts) {
              newContexts.add(lens.mapProgramMethod(context, definitions));
            }
          });
      return new ConcreteAccessContexts(newAccessesWithContexts);
    }
  }

  public static class UnknownAccessContexts extends AbstractAccessContexts {

    public static UnknownAccessContexts INSTANCE = new UnknownAccessContexts();

    private UnknownAccessContexts() {}

    public static UnknownAccessContexts getInstance() {
      return INSTANCE;
    }

    @Override
    void flattenAccessContexts(DexField field) {
      // Intentionally empty.
    }

    @Override
    void forEachAccessContext(Consumer<ProgramMethod> consumer) {
      throw new Unreachable("Should never be iterating the access contexts when they are unknown");
    }

    @Override
    boolean isAccessedInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      return true;
    }

    @Override
    boolean isAccessedOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) {
      return false;
    }

    @Override
    boolean isAccessedOutside(DexEncodedMethod method) {
      return true;
    }

    @Override
    int getNumberOfAccessContexts() {
      throw new Unreachable(
          "Should never be querying the number of access contexts when they are unknown");
    }

    @Override
    public boolean isEmpty() {
      return false;
    }

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

    @Override
    AbstractAccessContexts rewrittenWithLens(DexDefinitionSupplier definitions, GraphLens lens) {
      return this;
    }
  }
}
