package org.checkerframework.common.subtyping;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.subtyping.qual.Unqualified;
import org.checkerframework.framework.qual.DefaultFor;
import org.checkerframework.framework.qual.DefaultQualifierInHierarchy;
import org.checkerframework.framework.qual.SubtypeOf;
import org.checkerframework.framework.qual.TypeUseLocation;
import org.checkerframework.framework.type.AnnotationClassLoader;
import org.checkerframework.framework.util.defaults.QualifierDefaults;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.UserError;
import org.plumelib.reflection.Signatures;

/** Defines {@link #createSupportedTypeQualifiers}. */
public class SubtypingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {

  public SubtypingAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker);
    postInit();
  }

  @Override
  protected AnnotationClassLoader createAnnotationClassLoader() {
    return new SubtypingAnnotationClassLoader(checker);
  }

  @Override
  protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
    // Subtyping Checker doesn't have a qual directory, so we instantiate the loader here to
    // load externally declared annotations
    loader = createAnnotationClassLoader();

    String qualNames = checker.getOption("quals");
    String qualDirectories = checker.getOption("qualDirs");

    if (qualNames == null && qualDirectories == null) {
      throw new UserError("SubtypingChecker: missing required option. Use -Aquals or -AqualDirs.");
    }

    Set<Class<? extends Annotation>> qualSet = new LinkedHashSet<>();

    // load individually named qualifiers
    if (qualNames != null) {
      for (String qualName : qualNames.split(",")) {
        if (!Signatures.isBinaryName(qualName)) {
          throw new UserError("Malformed qualifier \"%s\" in -Aquals=%s", qualName, qualNames);
        }
        Class<? extends Annotation> anno = loader.loadExternalAnnotationClass(qualName);
        if (anno == null) {
          throw new UserError("Qualifier specified in -Aquals not found: " + qualName);
        }
        qualSet.add(anno);
      }
    }

    // load directories of qualifiers
    if (qualDirectories != null) {
      for (String dirName : qualDirectories.split(":")) {
        Set<Class<? extends Annotation>> annos =
            loader.loadExternalAnnotationClassesFromDirectory(dirName);
        if (annos.isEmpty()) {
          throw new UserError(
              "Directory specified in -AqualsDir contains no qualifiers: " + dirName);
        }
        qualSet.addAll(annos);
      }
    }

    if (qualSet.isEmpty()) {
      throw new UserError("SubtypingChecker: no qualifiers specified via -Aquals or -AqualDirs");
    }

    // check for subtype meta-annotation
    for (Class<? extends Annotation> qual : qualSet) {
      Annotation subtypeOfAnnotation = qual.getAnnotation(SubtypeOf.class);
      if (subtypeOfAnnotation != null) {
        for (Class<? extends Annotation> superqual : qual.getAnnotation(SubtypeOf.class).value()) {
          if (!qualSet.contains(superqual)) {
            throw new UserError(
                "SubtypingChecker: qualifier "
                    + qual
                    + " was specified via -Aquals but its super-qualifier "
                    + superqual
                    + " was not");
          }
        }
      }
    }

    return qualSet;
  }

  /**
   * If necessary, make Unqualified the default qualifier. Keep most logic in sync with super.
   *
   * @see
   *     org.checkerframework.framework.type.GenericAnnotatedTypeFactory#addCheckedCodeDefaults(org.checkerframework.framework.util.defaults.QualifierDefaults)
   */
  @Override
  protected void addCheckedCodeDefaults(QualifierDefaults defs) {
    boolean foundOtherwise = false;
    // Add defaults from @DefaultFor and @DefaultQualifierInHierarchy
    for (Class<? extends Annotation> qual : getSupportedTypeQualifiers()) {
      DefaultFor defaultFor = qual.getAnnotation(DefaultFor.class);
      if (defaultFor != null) {
        final TypeUseLocation[] locations = defaultFor.value();
        defs.addCheckedCodeDefaults(AnnotationBuilder.fromClass(elements, qual), locations);
        foundOtherwise =
            foundOtherwise || Arrays.asList(locations).contains(TypeUseLocation.OTHERWISE);
      }

      if (qual.getAnnotation(DefaultQualifierInHierarchy.class) != null) {
        defs.addCheckedCodeDefault(
            AnnotationBuilder.fromClass(elements, qual), TypeUseLocation.OTHERWISE);
        foundOtherwise = true;
      }
    }
    // If Unqualified is a supported qualifier, make it the default.
    AnnotationMirror unqualified = AnnotationBuilder.fromClass(elements, Unqualified.class);
    if (!foundOtherwise && this.isSupportedQualifier(unqualified)) {
      defs.addCheckedCodeDefault(unqualified, TypeUseLocation.OTHERWISE);
    }
  }
}
