package org.checkerframework.framework.testchecker.flowexpression;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.util.Elements;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.testchecker.flowexpression.qual.FEBottom;
import org.checkerframework.framework.testchecker.flowexpression.qual.FETop;
import org.checkerframework.framework.testchecker.flowexpression.qual.FlowExp;
import org.checkerframework.framework.type.MostlyNoElementQualifierHierarchy;
import org.checkerframework.framework.util.QualifierKind;
import org.checkerframework.framework.util.dependenttypes.DependentTypesHelper;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;

public class FlowExpressionAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
  private AnnotationMirror TOP, BOTTOM;

  /** The FlowExp.value field/element. */
  ExecutableElement flowExpValueElement =
      TreeUtils.getMethod(FlowExp.class, "value", 0, processingEnv);

  public FlowExpressionAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker);
    TOP = AnnotationBuilder.fromClass(elements, FETop.class);
    BOTTOM = AnnotationBuilder.fromClass(elements, FEBottom.class);
    postInit();
  }

  @Override
  protected DependentTypesHelper createDependentTypesHelper() {
    return new DependentTypesHelper(this);
  }

  @Override
  protected FlowExpressionQualifierHierarchy createQualifierHierarchy() {
    return new FlowExpressionQualifierHierarchy(this.getSupportedTypeQualifiers(), elements);
  }

  private class FlowExpressionQualifierHierarchy extends MostlyNoElementQualifierHierarchy {

    /**
     * Create a {@code FlowExpressionQualifierHierarchy}.
     *
     * @param qualifierClasses classes of annotations that are the qualifiers
     * @param elements element utils
     */
    public FlowExpressionQualifierHierarchy(
        Set<Class<? extends Annotation>> qualifierClasses, Elements elements) {
      super(qualifierClasses, elements);
    }

    @Override
    protected boolean isSubtypeWithElements(
        AnnotationMirror subAnno,
        QualifierKind subKind,
        AnnotationMirror superAnno,
        QualifierKind superKind) {
      List<String> subtypeExpressions =
          AnnotationUtils.getElementValueArray(subAnno, flowExpValueElement, String.class);
      List<String> supertypeExpressions =
          AnnotationUtils.getElementValueArray(superAnno, flowExpValueElement, String.class);
      return subtypeExpressions.containsAll(supertypeExpressions)
          && supertypeExpressions.containsAll(subtypeExpressions);
    }

    @Override
    protected AnnotationMirror leastUpperBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind lubKind) {
      if (qualifierKind1.getName() == FEBottom.class.getCanonicalName()) {
        return a2;
      } else if (qualifierKind2.getName() == FEBottom.class.getCanonicalName()) {
        return a1;
      }
      List<String> a1Expressions =
          AnnotationUtils.getElementValueArray(a1, flowExpValueElement, String.class);
      List<String> a2Expressions =
          AnnotationUtils.getElementValueArray(a2, flowExpValueElement, String.class);
      if (a1Expressions.containsAll(a2Expressions) && a2Expressions.containsAll(a1Expressions)) {
        return a1;
      }
      return TOP;
    }

    @Override
    protected AnnotationMirror greatestLowerBoundWithElements(
        AnnotationMirror a1,
        QualifierKind qualifierKind1,
        AnnotationMirror a2,
        QualifierKind qualifierKind2,
        QualifierKind glbKind) {
      if (qualifierKind1.getName() == FETop.class.getCanonicalName()) {
        return a2;
      } else if (qualifierKind2.getName() == FETop.class.getCanonicalName()) {
        return a1;
      }
      List<String> a1Expressions =
          AnnotationUtils.getElementValueArray(a1, flowExpValueElement, String.class);
      List<String> a2Expressions =
          AnnotationUtils.getElementValueArray(a2, flowExpValueElement, String.class);
      if (a1Expressions.containsAll(a2Expressions) && a2Expressions.containsAll(a1Expressions)) {
        return a1;
      }
      return BOTTOM;
    }
  }
}
