// Copyright (c) 2021, 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.ir.optimize.classinliner.analysis;

import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.utils.BooleanUtils;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSet;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;

/**
 * Non-trivial information (neither BOTTOM nor TOP) about a method's usage of a given parameter.
 *
 * <p>This is internal to the analysis, since {@link #methodCallsWithParameterAsReceiver} references
 * instructions from {@link com.android.tools.r8.ir.code.IRCode}, which makes it unsuited for being
 * stored in {@link com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo}.
 */
public class InternalNonEmptyParameterUsage extends ParameterUsage {

  private Set<DexType> castsWithParameter;
  private Set<DexField> fieldsReadFromParameter;
  private Set<InvokeMethodWithReceiver> methodCallsWithParameterAsReceiver;

  private boolean isParameterMutated;
  private boolean isParameterReturned;
  private boolean isParameterUsedAsLock;

  InternalNonEmptyParameterUsage(
      Set<DexType> castsWithParameter,
      Set<DexField> fieldsReadFromParameter,
      Set<InvokeMethodWithReceiver> methodCallsWithParameterAsReceiver,
      boolean isParameterMutated,
      boolean isParameterReturned,
      boolean isParameterUsedAsLock) {
    assert !castsWithParameter.isEmpty()
        || !fieldsReadFromParameter.isEmpty()
        || !methodCallsWithParameterAsReceiver.isEmpty()
        || isParameterMutated
        || isParameterReturned
        || isParameterUsedAsLock;
    this.castsWithParameter = castsWithParameter;
    this.fieldsReadFromParameter = fieldsReadFromParameter;
    this.methodCallsWithParameterAsReceiver = methodCallsWithParameterAsReceiver;
    this.isParameterMutated = isParameterMutated;
    this.isParameterReturned = isParameterReturned;
    this.isParameterUsedAsLock = isParameterUsedAsLock;
  }

  static Builder builder() {
    return new Builder();
  }

  Builder builderFromInstance() {
    return new Builder(this);
  }

  @Override
  ParameterUsage addCastWithParameter(DexType castType) {
    ImmutableSet.Builder<DexType> newCastsWithParameter = ImmutableSet.builder();
    newCastsWithParameter.addAll(castsWithParameter);
    newCastsWithParameter.add(castType);
    return new InternalNonEmptyParameterUsage(
        newCastsWithParameter.build(),
        fieldsReadFromParameter,
        methodCallsWithParameterAsReceiver,
        isParameterMutated,
        isParameterReturned,
        isParameterUsedAsLock);
  }

  @Override
  InternalNonEmptyParameterUsage addFieldReadFromParameter(DexField field) {
    ImmutableSet.Builder<DexField> newFieldsReadFromParameterBuilder = ImmutableSet.builder();
    newFieldsReadFromParameterBuilder.addAll(fieldsReadFromParameter);
    newFieldsReadFromParameterBuilder.add(field);
    return new InternalNonEmptyParameterUsage(
        castsWithParameter,
        newFieldsReadFromParameterBuilder.build(),
        methodCallsWithParameterAsReceiver,
        isParameterMutated,
        isParameterReturned,
        isParameterUsedAsLock);
  }

  @Override
  InternalNonEmptyParameterUsage addMethodCallWithParameterAsReceiver(
      InvokeMethodWithReceiver invoke) {
    ImmutableSet.Builder<InvokeMethodWithReceiver> newMethodCallsWithParameterAsReceiverBuilder =
        ImmutableSet.builder();
    newMethodCallsWithParameterAsReceiverBuilder.addAll(methodCallsWithParameterAsReceiver);
    newMethodCallsWithParameterAsReceiverBuilder.add(invoke);
    return new InternalNonEmptyParameterUsage(
        castsWithParameter,
        fieldsReadFromParameter,
        newMethodCallsWithParameterAsReceiverBuilder.build(),
        isParameterMutated,
        isParameterReturned,
        isParameterUsedAsLock);
  }

  @Override
  public InternalNonEmptyParameterUsage asInternalNonEmpty() {
    return this;
  }

  @Override
  ParameterUsage externalize() {
    ImmutableMultiset.Builder<DexMethod> methodCallsWithParameterAsReceiverBuilder =
        ImmutableMultiset.builder();
    methodCallsWithParameterAsReceiver.forEach(
        invoke -> methodCallsWithParameterAsReceiverBuilder.add(invoke.getInvokedMethod()));
    return new NonEmptyParameterUsage(
        castsWithParameter,
        fieldsReadFromParameter,
        methodCallsWithParameterAsReceiverBuilder.build(),
        isParameterMutated,
        isParameterReturned,
        isParameterUsedAsLock);
  }

  @Override
  public boolean isParameterMutated() {
    return isParameterMutated;
  }

  @Override
  public boolean isParameterReturned() {
    return isParameterReturned;
  }

  @Override
  public boolean isParameterUsedAsLock() {
    return isParameterUsedAsLock;
  }

  InternalNonEmptyParameterUsage join(InternalNonEmptyParameterUsage other) {
    return builderFromInstance()
        .addCastsWithParameter(other.castsWithParameter)
        .addFieldsReadFromParameter(other.fieldsReadFromParameter)
        .addMethodCallsWithParameterAsReceiver(other.methodCallsWithParameterAsReceiver)
        .joinIsReceiverMutated(other.isParameterMutated)
        .joinIsReceiverReturned(other.isParameterReturned)
        .joinIsReceiverUsedAsLock(other.isParameterUsedAsLock)
        .build();
  }

  @Override
  InternalNonEmptyParameterUsage setParameterMutated() {
    if (isParameterMutated) {
      return this;
    }
    return new InternalNonEmptyParameterUsage(
        castsWithParameter,
        fieldsReadFromParameter,
        methodCallsWithParameterAsReceiver,
        true,
        isParameterReturned,
        isParameterUsedAsLock);
  }

  @Override
  InternalNonEmptyParameterUsage setParameterReturned() {
    if (isParameterReturned) {
      return this;
    }
    return new InternalNonEmptyParameterUsage(
        castsWithParameter,
        fieldsReadFromParameter,
        methodCallsWithParameterAsReceiver,
        isParameterMutated,
        true,
        isParameterUsedAsLock);
  }

  @Override
  InternalNonEmptyParameterUsage setParameterUsedAsLock() {
    if (isParameterUsedAsLock) {
      return this;
    }
    return new InternalNonEmptyParameterUsage(
        castsWithParameter,
        fieldsReadFromParameter,
        methodCallsWithParameterAsReceiver,
        isParameterMutated,
        isParameterReturned,
        true);
  }

  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    }
    if (obj == null || obj.getClass() != getClass()) {
      return false;
    }
    InternalNonEmptyParameterUsage knownParameterUsage = (InternalNonEmptyParameterUsage) obj;
    return isParameterMutated == knownParameterUsage.isParameterMutated
        && isParameterReturned == knownParameterUsage.isParameterReturned
        && isParameterUsedAsLock == knownParameterUsage.isParameterUsedAsLock
        && castsWithParameter.equals(knownParameterUsage.castsWithParameter)
        && fieldsReadFromParameter.equals(knownParameterUsage.fieldsReadFromParameter)
        && methodCallsWithParameterAsReceiver.equals(
            knownParameterUsage.methodCallsWithParameterAsReceiver);
  }

  @Override
  public int hashCode() {
    int hash =
        31 * (31 * (31 + castsWithParameter.hashCode()) + fieldsReadFromParameter.hashCode())
            + methodCallsWithParameterAsReceiver.hashCode();
    assert hash
        == Objects.hash(
            castsWithParameter, fieldsReadFromParameter, methodCallsWithParameterAsReceiver);
    hash = (hash << 1) | BooleanUtils.intValue(isParameterMutated);
    hash = (hash << 1) | BooleanUtils.intValue(isParameterReturned);
    hash = (hash << 1) | BooleanUtils.intValue(isParameterUsedAsLock);
    return hash;
  }

  static class Builder {

    private ImmutableSet.Builder<DexType> castsWithParameterBuilder;
    private ImmutableSet.Builder<DexField> fieldsReadFromParameterBuilder;
    private ImmutableSet.Builder<InvokeMethodWithReceiver>
        methodCallsWithParameterAsReceiverBuilder;
    private boolean isParameterMutated;
    private boolean isParameterReturned;
    private boolean isParameterUsedAsLock;

    Builder() {
      castsWithParameterBuilder = ImmutableSet.builder();
      fieldsReadFromParameterBuilder = ImmutableSet.builder();
      methodCallsWithParameterAsReceiverBuilder = ImmutableSet.builder();
    }

    Builder(InternalNonEmptyParameterUsage methodBehavior) {
      castsWithParameterBuilder =
          ImmutableSet.<DexType>builder().addAll(methodBehavior.castsWithParameter);
      fieldsReadFromParameterBuilder =
          ImmutableSet.<DexField>builder().addAll(methodBehavior.fieldsReadFromParameter);
      methodCallsWithParameterAsReceiverBuilder =
          ImmutableSet.<InvokeMethodWithReceiver>builder()
              .addAll(methodBehavior.methodCallsWithParameterAsReceiver);
      isParameterMutated = methodBehavior.isParameterMutated;
      isParameterReturned = methodBehavior.isParameterReturned;
      isParameterUsedAsLock = methodBehavior.isParameterUsedAsLock;
    }

    Builder addCastWithParameter(DexType castType) {
      castsWithParameterBuilder.add(castType);
      return this;
    }

    Builder addCastsWithParameter(Collection<DexType> castTypes) {
      castsWithParameterBuilder.addAll(castTypes);
      return this;
    }

    Builder addFieldReadFromParameter(DexField fieldReadFromParameter) {
      fieldsReadFromParameterBuilder.add(fieldReadFromParameter);
      return this;
    }

    Builder addFieldsReadFromParameter(Collection<DexField> fieldsReadFromParameter) {
      fieldsReadFromParameterBuilder.addAll(fieldsReadFromParameter);
      return this;
    }

    Builder addMethodCallWithParameterAsReceiver(
        InvokeMethodWithReceiver methodCallWithParameterAsReceiver) {
      methodCallsWithParameterAsReceiverBuilder.add(methodCallWithParameterAsReceiver);
      return this;
    }

    Builder addMethodCallsWithParameterAsReceiver(
        Set<InvokeMethodWithReceiver> methodCallsWithParameterAsReceiver) {
      methodCallsWithParameterAsReceiverBuilder.addAll(methodCallsWithParameterAsReceiver);
      return this;
    }

    Builder joinIsReceiverMutated(boolean isParameterMutated) {
      this.isParameterMutated |= isParameterMutated;
      return this;
    }

    Builder joinIsReceiverReturned(boolean isParameterReturned) {
      this.isParameterReturned |= isParameterReturned;
      return this;
    }

    Builder joinIsReceiverUsedAsLock(boolean isParameterUsedAsLock) {
      this.isParameterUsedAsLock |= isParameterUsedAsLock;
      return this;
    }

    Builder setParameterMutated() {
      this.isParameterMutated = true;
      return this;
    }

    Builder setParameterReturned() {
      this.isParameterReturned = true;
      return this;
    }

    Builder setParameterUsedAsLock() {
      this.isParameterUsedAsLock = true;
      return this;
    }

    InternalNonEmptyParameterUsage build() {
      return new InternalNonEmptyParameterUsage(
          castsWithParameterBuilder.build(),
          fieldsReadFromParameterBuilder.build(),
          methodCallsWithParameterAsReceiverBuilder.build(),
          isParameterMutated,
          isParameterReturned,
          isParameterUsedAsLock);
    }
  }
}
