// Copyright (c) 2016, 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.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * List of parameter annotations.
 *
 * <p>Due to a javac bug that went unfixed for multiple Java versions, the JVM specification does
 * not require that the number of entries in the ParameterAnnotations attribute of a method matches
 * the number of parameters in the method prototype; the number of ParameterAnnotations entries may
 * be less than the number of prototype parameters for methods on inner classes.
 *
 * <p>There are two ways of accessing the parameter annotations:
 *
 * <ul>
 *   <li>Using {@link ParameterAnnotationsList#forEachAnnotation(Consumer)}
 *   <li>Using {@link ParameterAnnotationsList#size()}, {@link
 *       ParameterAnnotationsList#isMissing(int)} and {@link ParameterAnnotationsList#get(int)}
 * </ul>
 *
 * <p>The {@link ParameterAnnotationsList#forEachAnnotation(Consumer)} method visits all the {@link
 * DexAnnotation}s specified in the ParameterAnnotations attribute. In contrast, the {@link
 * ParameterAnnotationsList#size()} and {@link ParameterAnnotationsList#get(int)} methods may be
 * used to access the annotations on individual parameters; these methods automatically shift
 * parameter annotations up to mitigate the javac bug. The {@link
 * ParameterAnnotationsList#isMissing(int)} accessor is used to determine whether a given parameter
 * is missing in the ParameterAnnotations attribute.
 */
public class ParameterAnnotationsList extends DexItem {

  private static final ParameterAnnotationsList EMPTY_PARAMETER_ANNOTATIONS_LIST =
      new ParameterAnnotationsList();

  private final DexAnnotationSet[] values;
  private final int missingParameterAnnotations;

  public static ParameterAnnotationsList empty() {
    return EMPTY_PARAMETER_ANNOTATIONS_LIST;
  }

  private ParameterAnnotationsList() {
    this.values = DexAnnotationSet.EMPTY_ARRAY;
    this.missingParameterAnnotations = 0;
  }

  public ParameterAnnotationsList(DexAnnotationSet[] values) {
    this(values, 0);
  }

  public ParameterAnnotationsList(DexAnnotationSet[] values, int missingParameterAnnotations) {
    assert values != null && values.length > 0;
    this.values = values;
    this.missingParameterAnnotations = missingParameterAnnotations;
  }

  public int getAnnotableParameterCount() {
    return size();
  }

  @Override
  public int hashCode() {
    return Arrays.hashCode(values);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (other instanceof ParameterAnnotationsList) {
      return Arrays.equals(values, ((ParameterAnnotationsList) other).values);
    }
    return false;
  }

  public void collectIndexedItems(IndexedItemCollection indexedItems) {
    for (DexAnnotationSet value : values) {
      value.collectIndexedItems(indexedItems);
    }
  }

  @Override
  void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    // Collect values first so that the annotation sets have sorted themselves before adding this.
    collectAll(mixedItems, values);
    mixedItems.add(this);
  }

  public boolean isEmpty() {
    return values.length == 0;
  }

  /** Iterate over the {@link DexAnnotation}s of all parameters. */
  public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
    for (DexAnnotationSet parameterAnnotations : values) {
      for (DexAnnotation annotation : parameterAnnotations.annotations) {
        consumer.accept(annotation);
      }
    }
  }

  /**
   * Return the number of parameters in the method prototype, or zero if the method's parameters
   * have no annotations.
   */
  public int size() {
    return missingParameterAnnotations + values.length;
  }

  /**
   * Return the number of parameters specified in the ParameterAnnotations attribute, that is, the
   * number of parameters for which {@link ParameterAnnotationsList#isMissing(int)} returns false.
   */
  public int countNonMissing() {
    return values.length;
  }

  /**
   * Return true if the ParameterAnnotations attribute is missing an entry for this parameter. This
   * is sometimes the case for the first parameter in a method on an inner class.
   *
   * @param i Index of the parameter in the method prototype.
   */
  public boolean isMissing(int i) {
    assert i >= 0;
    return i < missingParameterAnnotations;
  }

  /**
   * Return the annotations on the {@code i}th parameter (indexed according to the method
   * prototype). If the parameter's annotation list is missing, or {@code i} is not less than the
   * number of parameters (see {@link ParameterAnnotationsList#isMissing(int)}), {@link
   * DexAnnotationSet#empty()} is returned.
   *
   * @param i Index of the parameter in the method prototype.
   */
  public DexAnnotationSet get(int i) {
    assert i >= 0;
    int adjustedIndex = i - missingParameterAnnotations;
    return (0 <= adjustedIndex && adjustedIndex < values.length)
        ? values[adjustedIndex]
        : DexAnnotationSet.empty();
  }

  /** Return a ParameterAnnotationsList extended to the given number of parameters. */
  public ParameterAnnotationsList withParameterCount(int parameterCount) {
    if (this == EMPTY_PARAMETER_ANNOTATIONS_LIST || parameterCount == size()) {
      return this;
    }
    if (parameterCount < size()) {
      // Generally, it should never be the case that parameterCount < size(). However, it may be
      // that the input has already been optimized (e.g., by Proguard), and that some optimization
      // has removed formal parameters without removing the corresponding parameters annotations.
      // In this case, we remove the excess annotations.
      DexAnnotationSet[] trimmedValues = new DexAnnotationSet[parameterCount];
      System.arraycopy(values, 0, trimmedValues, 0, parameterCount);
      return new ParameterAnnotationsList(trimmedValues, 0);
    }
    return new ParameterAnnotationsList(values, parameterCount - values.length);
  }

  /**
   * Return a new ParameterAnnotationsList that keeps only the annotations matched by {@code
   * filter}.
   */
  public ParameterAnnotationsList keepIf(Predicate<DexAnnotation> filter) {
    DexAnnotationSet[] filtered = null;
    boolean allEmpty = true;
    for (int i = 0; i < values.length; i++) {
      DexAnnotationSet updated = values[i].keepIf(filter);
      if (updated != values[i]) {
        if (filtered == null) {
          filtered = values.clone();
        }
        filtered[i] = updated;
      }
      if (!updated.isEmpty()) {
        allEmpty = false;
      }
    }
    if (filtered == null) {
      return this;
    }
    if (allEmpty) {
      return ParameterAnnotationsList.empty();
    }
    return new ParameterAnnotationsList(filtered, missingParameterAnnotations);
  }

  public ParameterAnnotationsList rewrite(Function<DexAnnotationSet, DexAnnotationSet> mapper) {
    DexAnnotationSet[] rewritten = ArrayUtils.map(DexAnnotationSet[].class, values, mapper);
    if (rewritten != values) {
      return new ParameterAnnotationsList(rewritten, missingParameterAnnotations);
    }
    return this;
  }
}
