package org.checkerframework.dataflow.expression;

import java.util.List;
import java.util.Objects;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.StringsPlume;

/** JavaExpression for array creations. {@code new String[]()}. */
public class ArrayCreation extends JavaExpression {

  /**
   * List of dimensions expressions. A {code null} element means that there is no dimension
   * expression for the given array level.
   */
  protected final List<@Nullable JavaExpression> dimensions;
  /** List of initializers. */
  protected final List<JavaExpression> initializers;

  /**
   * Creates an ArrayCreation object.
   *
   * @param type array type
   * @param dimensions list of dimension expressions; a {code null} element means that there is no
   *     dimension expression for the given array level.
   * @param initializers list of initializer expressions
   */
  public ArrayCreation(
      TypeMirror type,
      List<@Nullable JavaExpression> dimensions,
      List<JavaExpression> initializers) {
    super(type);
    assert type.getKind() == TypeKind.ARRAY;
    this.dimensions = dimensions;
    this.initializers = initializers;
  }

  /**
   * Returns a list representing the dimensions of this array creation. A {code null} element means
   * that there is no dimension expression for the given array level.
   *
   * @return a list representing the dimensions of this array creation
   */
  public List<@Nullable JavaExpression> getDimensions() {
    return dimensions;
  }

  public List<JavaExpression> getInitializers() {
    return initializers;
  }

  @Override
  public boolean containsOfClass(Class<? extends JavaExpression> clazz) {
    for (JavaExpression n : dimensions) {
      if (n != null && n.getClass() == clazz) {
        return true;
      }
    }
    for (JavaExpression n : initializers) {
      if (n.getClass() == clazz) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean isDeterministic(AnnotationProvider provider) {
    return listIsDeterministic(dimensions, provider) && listIsDeterministic(initializers, provider);
  }

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

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

  @Override
  public int hashCode() {
    return Objects.hash(dimensions, initializers, getType().toString());
  }

  @Override
  public boolean equals(@Nullable Object obj) {
    if (!(obj instanceof ArrayCreation)) {
      return false;
    }
    ArrayCreation other = (ArrayCreation) obj;
    return this.dimensions.equals(other.getDimensions())
        && this.initializers.equals(other.getInitializers())
        // It might be better to use Types.isSameType(getType(), other.getType()), but I
        // don't have a Types object.
        && getType().toString().equals(other.getType().toString());
  }

  @Override
  public boolean syntacticEquals(JavaExpression je) {
    if (!(je instanceof ArrayCreation)) {
      return false;
    }
    ArrayCreation other = (ArrayCreation) je;
    return JavaExpression.syntacticEqualsList(this.dimensions, other.dimensions)
        && JavaExpression.syntacticEqualsList(this.initializers, other.initializers)
        && getType().toString().equals(other.getType().toString());
  }

  @Override
  public boolean containsSyntacticEqualJavaExpression(JavaExpression other) {
    return syntacticEquals(other)
        || JavaExpression.listContainsSyntacticEqualJavaExpression(dimensions, other)
        || JavaExpression.listContainsSyntacticEqualJavaExpression(initializers, other);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    if (dimensions.isEmpty()) {
      sb.append("new " + type);
    } else {
      sb.append("new " + TypesUtils.getInnermostComponentType((ArrayType) type));
      for (JavaExpression dim : dimensions) {
        sb.append("[");
        sb.append(dim == null ? "" : dim);
        sb.append("]");
      }
    }
    if (!initializers.isEmpty()) {
      sb.append(" {");
      sb.append(StringsPlume.join(", ", initializers));
      sb.append("}");
    }
    return sb.toString();
  }

  @Override
  public String toStringDebug() {
    return "\""
        + super.toStringDebug()
        + "\""
        + " type="
        + type
        + " dimensions="
        + dimensions
        + " initializers="
        + initializers;
  }

  @Override
  public <R, P> R accept(JavaExpressionVisitor<R, P> visitor, P p) {
    return visitor.visitArrayCreation(this, p);
  }
}
