/*
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.auto.common;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static javax.lang.model.util.ElementFilter.methodsIn;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;

/**
 * A simple implementation of the {@link AnnotationMirror} interface.
 *
 * <p>This type implements {@link #equals(Object)} and {@link #hashCode()} using {@link
 * AnnotationMirrors#equivalence} in accordance with the {@link AnnotationMirror} spec. Some {@link
 * AnnotationMirror}s, however, do not correctly implement equals, you should always compare them
 * using {@link AnnotationMirrors#equivalence} anyway.
 */
public final class SimpleAnnotationMirror implements AnnotationMirror {
  private final TypeElement annotationType;
  private final ImmutableMap<String, ? extends AnnotationValue> namedValues;
  private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues;

  private SimpleAnnotationMirror(
      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
    checkArgument(
        annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE),
        "annotationType must be an annotation: %s",
        annotationType);
    Map<String, AnnotationValue> values = new LinkedHashMap<>();
    Map<String, AnnotationValue> unusedValues = new LinkedHashMap<>(namedValues);
    List<String> missingMembers = new ArrayList<>();
    for (ExecutableElement method : methodsIn(annotationType.getEnclosedElements())) {
      String memberName = method.getSimpleName().toString();
      if (unusedValues.containsKey(memberName)) {
        values.put(memberName, unusedValues.remove(memberName));
      } else if (method.getDefaultValue() != null) {
        values.put(memberName, method.getDefaultValue());
      } else {
        missingMembers.add(memberName);
      }
    }
    
    checkArgument(
        unusedValues.isEmpty(),
        "namedValues has entries for members that are not in %s: %s",
        annotationType,
        unusedValues);
    checkArgument(
        missingMembers.isEmpty(), "namedValues is missing entries for: %s", missingMembers);

    this.annotationType = annotationType;
    this.namedValues = ImmutableMap.copyOf(namedValues);
    this.elementValues =
        methodsIn(annotationType.getEnclosedElements())
            .stream()
            .collect(toImmutableMap(e -> e, e -> values.get(e.getSimpleName().toString())));
  }

  /**
   * An object representing an {@linkplain ElementKind#ANNOTATION_TYPE annotation} instance. If
   * {@code annotationType} has any annotation members, they must have default values.
   */
  public static AnnotationMirror of(TypeElement annotationType) {
    return of(annotationType, ImmutableMap.of());
  }

  /**
   * An object representing an {@linkplain ElementKind#ANNOTATION_TYPE annotation} instance. If
   * {@code annotationType} has any annotation members, they must either be present in {@code
   * namedValues} or have default values.
   */
  public static AnnotationMirror of(
      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
    return new SimpleAnnotationMirror(annotationType, namedValues);
  }

  @Override
  public DeclaredType getAnnotationType() {
    return MoreTypes.asDeclared(annotationType.asType());
  }

  @Override
  public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() {
    return elementValues;
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName());
    if (!namedValues.isEmpty()) {
      builder
          .append('(')
          .append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues))
          .append(')');
    }
    return builder.toString();
  }

  @Override
  public boolean equals(Object other) {
    return other instanceof AnnotationMirror
        && AnnotationMirrors.equivalence().equivalent(this, (AnnotationMirror) other);
  }

  @Override
  public int hashCode() {
    return AnnotationMirrors.equivalence().hash(this);
  }
}
