package org.checkerframework.framework.type.visitor;

import java.util.Iterator;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.javacutil.BugInCF;

/**
 * An {@link AnnotatedTypeScanner} that scans two {@link AnnotatedTypeMirror}s simultaneously and
 * performs {@link #defaultAction(AnnotatedTypeMirror, AnnotatedTypeMirror)} on the pair. Both
 * AnnotatedTypeMirrors must have the same structure, or a subclass must arrange not to continue
 * recursing past the point at which their structure diverges.
 *
 * <p>If the default action does not return a result, then {@code R} should be {@link Void} and
 * {@code DoubleAnnotatedTypeScanner()} should be used to construct the scanner. If the default
 * action returns a result, then specify a {@link #reduce} function and use {@code
 * DoubleAnnotatedTypeScanner(Reduce, Object)}.
 *
 * @see AnnotatedTypeScanner
 * @param <R> the result of scanning the two {@code AnnotatedTypeMirror}s
 */
public abstract class DoubleAnnotatedTypeScanner<R>
    extends AnnotatedTypeScanner<R, AnnotatedTypeMirror> {

  /**
   * Constructs an AnnotatedTypeScanner where the reduce function returns the first result if it is
   * nonnull; otherwise the second result is returned. The default result is {@code null}.
   */
  protected DoubleAnnotatedTypeScanner() {
    super();
  }

  /**
   * Creates a scanner with the given {@code reduce} function and {@code defaultResult}.
   *
   * @param reduce function used to combine the results of scan
   * @param defaultResult result to use by default
   */
  protected DoubleAnnotatedTypeScanner(Reduce<R> reduce, R defaultResult) {
    super(reduce, defaultResult);
  }

  /**
   * Called by default for any visit method that is not overridden.
   *
   * @param type the type to visit
   * @param p a visitor-specified parameter
   * @return a visitor-specified result
   */
  protected abstract R defaultAction(AnnotatedTypeMirror type, AnnotatedTypeMirror p);

  /**
   * Scans {@code types1} and {@code types2}. If they are empty, then {@link #defaultResult} is
   * returned.
   *
   * @param types1 types
   * @param types2 types
   * @return the result of scanning and reducing all the types in {@code types1} and {@code types2}
   *     or {@link #defaultResult} if they are empty
   */
  protected R scan(
      Iterable<? extends AnnotatedTypeMirror> types1,
      Iterable<? extends AnnotatedTypeMirror> types2) {
    if (types1 == null || types2 == null) {
      return defaultResult;
    }
    R r = defaultResult;
    boolean first = true;
    Iterator<? extends AnnotatedTypeMirror> iter1 = types1.iterator();
    Iterator<? extends AnnotatedTypeMirror> iter2 = types2.iterator();
    while (iter1.hasNext() && iter2.hasNext()) {
      r = (first ? scan(iter1.next(), iter2.next()) : scanAndReduce(iter1.next(), iter2.next(), r));
      first = false;
    }
    return r;
  }

  /**
   * Run {@link #scan} on types and p, then run {@link #reduce} on the result (plus r) to return a
   * single element.
   */
  protected R scanAndReduce(
      Iterable<? extends AnnotatedTypeMirror> types,
      Iterable<? extends AnnotatedTypeMirror> p,
      R r) {
    return reduce(scan(types, p), r);
  }

  @Override
  protected final R scanAndReduce(
      Iterable<? extends AnnotatedTypeMirror> types, AnnotatedTypeMirror p, R r) {
    throw new BugInCF(
        "DoubleAnnotatedTypeScanner.scanAndReduce: "
            + p
            + " is not Iterable<? extends AnnotatedTypeMirror>");
  }

  @Override
  protected R scan(AnnotatedTypeMirror type, AnnotatedTypeMirror p) {
    return reduce(super.scan(type, p), defaultAction(type, p));
  }

  @Override
  public final R visitDeclared(AnnotatedDeclaredType type, AnnotatedTypeMirror p) {
    assert p instanceof AnnotatedDeclaredType : p;
    R r = scan(type.getTypeArguments(), ((AnnotatedDeclaredType) p).getTypeArguments());
    if (type.getEnclosingType() != null) {
      r = scanAndReduce(type.getEnclosingType(), ((AnnotatedDeclaredType) p).getEnclosingType(), r);
    }
    return r;
  }

  @Override
  public final R visitArray(AnnotatedArrayType type, AnnotatedTypeMirror p) {
    assert p instanceof AnnotatedArrayType : p;
    R r = scan(type.getComponentType(), ((AnnotatedArrayType) p).getComponentType());
    return r;
  }

  @Override
  public final R visitExecutable(AnnotatedExecutableType type, AnnotatedTypeMirror p) {
    assert p instanceof AnnotatedExecutableType : p;
    AnnotatedExecutableType ex = (AnnotatedExecutableType) p;
    R r = scan(type.getReturnType(), ex.getReturnType());
    if (type.getReceiverType() != null) {
      r = scanAndReduce(type.getReceiverType(), ex.getReceiverType(), r);
    }
    r = scanAndReduce(type.getParameterTypes(), ex.getParameterTypes(), r);
    r = scanAndReduce(type.getThrownTypes(), ex.getThrownTypes(), r);
    r = scanAndReduce(type.getTypeVariables(), ex.getTypeVariables(), r);
    return r;
  }

  @Override
  public R visitTypeVariable(AnnotatedTypeVariable type, AnnotatedTypeMirror p) {
    if (visitedNodes.containsKey(type)) {
      return visitedNodes.get(type);
    }
    visitedNodes.put(type, null);

    R r;
    if (p instanceof AnnotatedTypeVariable) {
      AnnotatedTypeVariable tv = (AnnotatedTypeVariable) p;
      r = scan(type.getLowerBound(), tv.getLowerBound());
      visitedNodes.put(type, r);
      r = scanAndReduce(type.getUpperBound(), tv.getUpperBound(), r);
      visitedNodes.put(type, r);
    } else {
      r = scan(type.getLowerBound(), p.getErased());
      visitedNodes.put(type, r);
      r = scanAndReduce(type.getUpperBound(), p.getErased(), r);
      visitedNodes.put(type, r);
    }
    return r;
  }

  @Override
  public R visitWildcard(AnnotatedWildcardType type, AnnotatedTypeMirror p) {
    if (visitedNodes.containsKey(type)) {
      return visitedNodes.get(type);
    }
    visitedNodes.put(type, null);

    R r;
    if (p instanceof AnnotatedWildcardType) {
      AnnotatedWildcardType w = (AnnotatedWildcardType) p;
      r = scan(type.getExtendsBound(), w.getExtendsBound());
      visitedNodes.put(type, r);
      r = scanAndReduce(type.getSuperBound(), w.getSuperBound(), r);
      visitedNodes.put(type, r);
    } else {
      r = scan(type.getExtendsBound(), p.getErased());
      visitedNodes.put(type, r);
      r = scanAndReduce(type.getSuperBound(), p.getErased(), r);
      visitedNodes.put(type, r);
    }
    return r;
  }

  @Override
  public R visitIntersection(AnnotatedIntersectionType type, AnnotatedTypeMirror p) {
    assert p instanceof AnnotatedIntersectionType : p;

    if (visitedNodes.containsKey(type)) {
      return visitedNodes.get(type);
    }
    visitedNodes.put(type, null);
    R r = scan(type.getBounds(), ((AnnotatedIntersectionType) p).getBounds());
    return r;
  }

  @Override
  public R visitUnion(AnnotatedUnionType type, AnnotatedTypeMirror p) {
    assert p instanceof AnnotatedUnionType : p;
    if (visitedNodes.containsKey(type)) {
      return visitedNodes.get(type);
    }
    visitedNodes.put(type, null);
    R r = scan(type.getAlternatives(), ((AnnotatedUnionType) p).getAlternatives());
    return r;
  }
}
