/*
 * Copyright 2019 The Android Open Source Project
 *
 * 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 android.processor.view.inspector;

import android.processor.view.inspector.InspectableClassModel.IntEnumEntry;
import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
import android.processor.view.inspector.InspectableClassModel.Property;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.NoType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;

/**
 * Process {@code @InspectableProperty} annotations.
 *
 * @see android.view.inspector.InspectableProperty
 */
public final class InspectablePropertyProcessor implements ModelProcessor {
    private final String mQualifiedName;
    private final ProcessingEnvironment mProcessingEnv;
    private final AnnotationUtils mAnnotationUtils;

    /**
     * Regex that matches methods names of the form {@code #getValue()}.
     */
    private static final Pattern GETTER_GET_PREFIX = Pattern.compile("\\Aget[A-Z]");

    /**
     * Regex that matches method name of the form {@code #isPredicate()}.
     */
    private static final Pattern GETTER_IS_PREFIX = Pattern.compile("\\Ais[A-Z]");

    /**
     * Set of android and androidx annotation qualified names for colors packed into {@code int}.
     *
     * @see android.annotation.ColorInt
     */
    private static final String[] COLOR_INT_ANNOTATION_NAMES = {
            "android.annotation.ColorInt",
            "androidx.annotation.ColorInt"};

    /**
     * Set of android and androidx annotation qualified names for colors packed into {@code long}.
     *
     * @see android.annotation.ColorLong
     */
    private static final String[] COLOR_LONG_ANNOTATION_NAMES = {
            "android.annotation.ColorLong",
            "androidx.annotation.ColorLong"};

    /**
     * @param annotationQualifiedName The qualified name of the annotation to process
     * @param processingEnv           The processing environment from the parent processor
     */
    public InspectablePropertyProcessor(
            String annotationQualifiedName,
            ProcessingEnvironment processingEnv) {
        mQualifiedName = annotationQualifiedName;
        mProcessingEnv = processingEnv;
        mAnnotationUtils = new AnnotationUtils(processingEnv);
    }

    @Override
    public void process(Element element, InspectableClassModel model) {
        try {
            final AnnotationMirror annotation =
                    mAnnotationUtils.exactlyOneMirror(mQualifiedName, element);
            final ExecutableElement getter = ensureGetter(element);
            final Property property = buildProperty(getter, annotation);

            model.getProperty(property.getName()).ifPresent(p -> {
                throw new ProcessingException(
                        String.format(
                                "Property \"%s\" is already defined on #%s().",
                                p.getName(),
                                p.getGetter()),
                        getter,
                        annotation);
            });

            model.putProperty(property);
        } catch (ProcessingException processingException) {
            processingException.print(mProcessingEnv.getMessager());
        }
    }

    /**
     * Check that an element is shaped like a getter.
     *
     * @param element An element that hopefully represents a getter
     * @return An {@link ExecutableElement} that represents a getter method.
     * @throws ProcessingException if the element isn't a getter
     */
    private ExecutableElement ensureGetter(Element element) {
        if (element.getKind() != ElementKind.METHOD) {
            throw new ProcessingException(
                    String.format("Expected a method, got a %s", element.getKind()),
                    element);
        }

        final ExecutableElement method = (ExecutableElement) element;
        final Set<Modifier> modifiers = method.getModifiers();

        if (modifiers.contains(Modifier.PRIVATE)) {
            throw new ProcessingException(
                    "Property getter methods must not be private.",
                    element);
        }

        if (modifiers.contains(Modifier.ABSTRACT)) {
            throw new ProcessingException(
                    "Property getter methods must not be abstract.",
                    element);
        }

        if (modifiers.contains(Modifier.STATIC)) {
            throw new ProcessingException(
                    "Property getter methods must not be static.",
                    element);
        }

        if (!method.getParameters().isEmpty()) {
            throw new ProcessingException(
                    String.format(
                            "Expected a getter method to take no parameters, "
                                    + "but got %d parameters.",
                            method.getParameters().size()),
                    element);
        }

        if (method.isVarArgs()) {
            throw new ProcessingException(
                    "Expected a getter method to take no arguments, but got a var args method.",
                    element);
        }

        if (method.getReturnType() instanceof NoType) {
            throw new ProcessingException(
                    "Expected a getter to have a return type, got void.",
                    element);
        }

        return method;
    }

    /**
     * Build a {@link Property} from a getter and an inspectable property annotation.
     *
     * @param getter     An element representing the getter to build from
     * @param annotation A mirror of an inspectable property-shaped annotation
     * @return A property for the getter and annotation
     * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled
     */
    private Property buildProperty(ExecutableElement getter, AnnotationMirror annotation) {
        final String name = mAnnotationUtils
                .typedValueByName("name", String.class, getter, annotation)
                .orElseGet(() -> inferPropertyNameFromGetter(getter));

        final Property property = new Property(
                name,
                getter.getSimpleName().toString(),
                determinePropertyType(getter, annotation));

        mAnnotationUtils
                .typedValueByName("hasAttributeId", Boolean.class, getter, annotation)
                .ifPresent(property::setAttributeIdInferrableFromR);

        mAnnotationUtils
                .typedValueByName("attributeId", Integer.class, getter, annotation)
                .ifPresent(property::setAttributeId);

        switch (property.getType()) {
            case INT_ENUM:
                property.setIntEnumEntries(processEnumMapping(getter, annotation));
                break;
            case INT_FLAG:
                property.setIntFlagEntries(processFlagMapping(getter, annotation));
                break;
        }

        return property;
    }

    /**
     * Determine the property type from the annotation, return type, or context clues.
     *
     * @param getter     An element representing the getter to build from
     * @param annotation A mirror of an inspectable property-shaped annotation
     * @return The resolved property type
     * @throws ProcessingException If the property type cannot be resolved or is invalid
     * @see android.view.inspector.InspectableProperty#valueType()
     */
    private Property.Type determinePropertyType(
            ExecutableElement getter,
            AnnotationMirror annotation) {

        final String valueType = mAnnotationUtils
                .untypedValueByName("valueType", getter, annotation)
                .map(Object::toString)
                .orElse("INFERRED");

        final Property.Type returnType = convertReturnTypeToPropertyType(getter);

        final boolean hasColor = hasColorAnnotation(getter);
        final Optional<AnnotationValue> enumMapping =
                mAnnotationUtils.valueByName("enumMapping", annotation);
        final Optional<AnnotationValue> flagMapping =
                mAnnotationUtils.valueByName("flagMapping", annotation);

        if (returnType != Property.Type.INT) {
            enumMapping.ifPresent(value -> {
                throw new ProcessingException(
                        String.format(
                                "Can only use enumMapping on int types, got %s.",
                                returnType.toString().toLowerCase()),
                        getter,
                        annotation,
                        value);
            });
            flagMapping.ifPresent(value -> {
                throw new ProcessingException(
                        String.format(
                                "Can only use flagMapping on int types, got %s.",
                                returnType.toString().toLowerCase()),
                        getter,
                        annotation,
                        value);
            });
        }

        switch (valueType) {
            case "INFERRED":
                if (hasColor) {
                    enumMapping.ifPresent(value -> {
                        throw new ProcessingException(
                                "Cannot use enumMapping on a color type.",
                                getter,
                                annotation,
                                value);
                    });
                    flagMapping.ifPresent(value -> {
                        throw new ProcessingException(
                                "Cannot use flagMapping on a color type.",
                                getter,
                                annotation,
                                value);
                    });
                    return Property.Type.COLOR;
                } else if (enumMapping.isPresent()) {
                    flagMapping.ifPresent(value -> {
                        throw new ProcessingException(
                                "Cannot use flagMapping and enumMapping simultaneously.",
                                getter,
                                annotation,
                                value);
                    });
                    return Property.Type.INT_ENUM;
                } else if (flagMapping.isPresent()) {
                    return Property.Type.INT_FLAG;
                } else {
                    return returnType;
                }
            case "NONE":
                return returnType;
            case "COLOR":
                switch (returnType) {
                    case COLOR:
                    case INT:
                    case LONG:
                        return Property.Type.COLOR;
                    default:
                        throw new ProcessingException(
                                "Color must be a long, integer, or android.graphics.Color",
                                getter,
                                annotation);
                }
            case "GRAVITY":
                requirePackedIntToReturnInt("Gravity", returnType, getter, annotation);
                return Property.Type.GRAVITY;
            case "INT_ENUM":
                requirePackedIntToReturnInt("IntEnum", returnType, getter, annotation);
                return Property.Type.INT_ENUM;
            case "INT_FLAG":
                requirePackedIntToReturnInt("IntFlag", returnType, getter, annotation);
                return Property.Type.INT_FLAG;
            default:
                throw new ProcessingException(
                        String.format("Unknown value type enumeration value: %s", valueType),
                        getter,
                        annotation);
        }
    }

    /**
     * Get a property type from the return type of a getter.
     *
     * @param getter The getter to extract the return type of
     * @return The property type returned by the getter
     * @throws ProcessingException If the return type is not a primitive or an object
     */
    private Property.Type convertReturnTypeToPropertyType(ExecutableElement getter) {
        final TypeMirror returnType = getter.getReturnType();

        switch (unboxType(returnType)) {
            case BOOLEAN:
                return Property.Type.BOOLEAN;
            case BYTE:
                return Property.Type.BYTE;
            case CHAR:
                return Property.Type.CHAR;
            case DOUBLE:
                return Property.Type.DOUBLE;
            case FLOAT:
                return Property.Type.FLOAT;
            case INT:
                return Property.Type.INT;
            case LONG:
                return Property.Type.LONG;
            case SHORT:
                return Property.Type.SHORT;
            case DECLARED:
                if (isColorType(returnType)) {
                    return Property.Type.COLOR;
                } else {
                    return Property.Type.OBJECT;
                }
            case ARRAY:
                return Property.Type.OBJECT;
            default:
                throw new ProcessingException(
                        String.format("Unsupported return type %s.", returnType),
                        getter);
        }
    }

    /**
     * Require that a value type packed into an integer be on a getter that returns an int.
     *
     * @param typeName   The name of the type to use in the exception
     * @param returnType The return type of the getter to check
     * @param getter     The getter, to use in the exception
     * @param annotation The annotation, to use in the exception
     * @throws ProcessingException If the return type is not an int
     */
    private static void requirePackedIntToReturnInt(
            String typeName,
            Property.Type returnType,
            ExecutableElement getter,
            AnnotationMirror annotation) {
        if (returnType != Property.Type.INT) {
            throw new ProcessingException(
                    String.format(
                            "%s can only be defined on a method that returns int, got %s.",
                            typeName,
                            returnType.toString().toLowerCase()),
                    getter,
                    annotation);
        }
    }

    /**
     * Determine if a getter is annotated with color annotation matching its return type.
     *
     * Note that an {@code int} return value annotated with {@link android.annotation.ColorLong} is
     * not considered to be annotated, nor is a {@code long} annotated with
     * {@link android.annotation.ColorInt}.
     *
     * @param getter The getter to query
     * @return True if the getter has a color annotation, false otherwise
     */
    private boolean hasColorAnnotation(ExecutableElement getter) {
        switch (unboxType(getter.getReturnType())) {
            case INT:
                for (String name : COLOR_INT_ANNOTATION_NAMES) {
                    if (mAnnotationUtils.hasAnnotation(getter, name)) {
                        return true;
                    }
                }
                return false;
            case LONG:
                for (String name : COLOR_LONG_ANNOTATION_NAMES) {
                    if (mAnnotationUtils.hasAnnotation(getter, name)) {
                        return true;
                    }
                }
                return false;
            default:
                return false;
        }
    }

    /**
     * Infer a property name from a getter method.
     *
     * If the method is prefixed with {@code get}, the prefix will be stripped, and the
     * capitalization fixed. E.g.: {@code getSomeProperty} to {@code someProperty}.
     *
     * Additionally, if the method's return type is a boolean, an {@code is} prefix will also be
     * stripped. E.g.: {@code isPropertyEnabled} to {@code propertyEnabled}.
     *
     * Failing that, this method will just return the full name of the getter.
     *
     * @param getter An element representing a getter
     * @return A string property name
     */
    private String inferPropertyNameFromGetter(ExecutableElement getter) {
        final String name = getter.getSimpleName().toString();

        if (GETTER_GET_PREFIX.matcher(name).find()) {
            return name.substring(3, 4).toLowerCase() + name.substring(4);
        } else if (isBoolean(getter.getReturnType()) && GETTER_IS_PREFIX.matcher(name).find()) {
            return name.substring(2, 3).toLowerCase() + name.substring(3);
        } else {
            return name;
        }
    }

    /**
     * Build a model of an {@code int} enumeration mapping from annotation values.
     *
     * This method only handles the one-to-one mapping of mirrors of
     * {@link android.view.inspector.InspectableProperty.EnumMap} annotations into
     * {@link IntEnumEntry} objects. Further validation should be handled elsewhere
     *
     * @see android.view.inspector.IntEnumMapping
     * @see android.view.inspector.InspectableProperty#enumMapping()
     * @param getter The getter of the property, used for exceptions
     * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to
     *                   extract enum mapping values from.
     * @return A list of int enum entries, in the order specified in source
     * @throws ProcessingException if mapping doesn't exist or is invalid
     */
    private List<IntEnumEntry> processEnumMapping(
            ExecutableElement getter,
            AnnotationMirror annotation) {
        List<AnnotationMirror> enumAnnotations = mAnnotationUtils.typedArrayValuesByName(
                "enumMapping", AnnotationMirror.class, getter, annotation);
        List<IntEnumEntry> enumEntries = new ArrayList<>(enumAnnotations.size());

        if (enumAnnotations.isEmpty()) {
            throw new ProcessingException(
                    "Encountered an empty array for enumMapping", getter, annotation);
        }

        for (AnnotationMirror enumAnnotation : enumAnnotations) {
            final String name = mAnnotationUtils.typedValueByName(
                    "name", String.class, getter, enumAnnotation)
                    .orElseThrow(() -> {
                        throw new ProcessingException(
                                "Name is required for @EnumMap",
                                getter,
                                enumAnnotation);
                    });

            final int value = mAnnotationUtils.typedValueByName(
                    "value", Integer.class, getter, enumAnnotation)
                    .orElseThrow(() -> {
                        throw new ProcessingException(
                                "Value is required for @EnumMap",
                                getter,
                                enumAnnotation);
                    });

            enumEntries.add(new IntEnumEntry(name, value));
        }

        return enumEntries;
    }

    /**
     * Build a model of an {@code int} flag mapping from annotation values.
     *
     * This method only handles the one-to-one mapping of mirrors of
     * {@link android.view.inspector.InspectableProperty.FlagMap} annotations into
     * {@link IntFlagEntry} objects. Further validation should be handled elsewhere
     *
     * @see android.view.inspector.IntFlagMapping
     * @see android.view.inspector.InspectableProperty#flagMapping()
     * @param getter The getter of the property, used for exceptions
     * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to
     *                   extract flag mapping values from.
     * @return A list of int flags entries, in the order specified in source
     * @throws ProcessingException if mapping doesn't exist or is invalid
     */
    private List<IntFlagEntry> processFlagMapping(
            ExecutableElement getter,
            AnnotationMirror annotation) {
        List<AnnotationMirror> flagAnnotations = mAnnotationUtils.typedArrayValuesByName(
                "flagMapping", AnnotationMirror.class, getter, annotation);
        List<IntFlagEntry> flagEntries = new ArrayList<>(flagAnnotations.size());

        if (flagAnnotations.isEmpty()) {
            throw new ProcessingException(
                    "Encountered an empty array for flagMapping", getter, annotation);
        }

        for (AnnotationMirror flagAnnotation : flagAnnotations) {
            final String name = mAnnotationUtils.typedValueByName(
                    "name", String.class, getter, flagAnnotation)
                    .orElseThrow(() -> {
                        throw new ProcessingException(
                                "Name is required for @FlagMap",
                                getter,
                                flagAnnotation);
                    });

            final int target = mAnnotationUtils.typedValueByName(
                    "target", Integer.class, getter, flagAnnotation)
                    .orElseThrow(() -> {
                        throw new ProcessingException(
                                "Target is required for @FlagMap",
                                getter,
                                flagAnnotation);
                    });

            final Optional<Integer> mask = mAnnotationUtils.typedValueByName(
                    "mask", Integer.class, getter, flagAnnotation);

            if (mask.isPresent()) {
                flagEntries.add(new IntFlagEntry(name, target, mask.get()));
            } else {
                flagEntries.add(new IntFlagEntry(name, target));
            }
        }

        return flagEntries;
    }

    /**
     * Determine if a {@link TypeMirror} is a boxed or unboxed boolean.
     *
     * @param type The type mirror to check
     * @return True if the type is a boolean
     */
    private boolean isBoolean(TypeMirror type) {
        if (type.getKind() == TypeKind.DECLARED) {
            return mProcessingEnv.getTypeUtils().unboxedType(type).getKind() == TypeKind.BOOLEAN;
        } else {
            return type.getKind() == TypeKind.BOOLEAN;
        }
    }

    /**
     * Unbox a type mirror if it represents a boxed type, otherwise pass it through.
     *
     * @param typeMirror The type mirror to unbox
     * @return The same type mirror, or an unboxed primitive version
     */
    private TypeKind unboxType(TypeMirror typeMirror) {
        final TypeKind typeKind = typeMirror.getKind();

        if (typeKind.isPrimitive()) {
            return typeKind;
        } else if (typeKind == TypeKind.DECLARED) {
            try {
                return mProcessingEnv.getTypeUtils().unboxedType(typeMirror).getKind();
            } catch (IllegalArgumentException e) {
                return typeKind;
            }
        } else {
            return typeKind;
        }
    }

    /**
     * Determine if a type mirror represents a subtype of {@link android.graphics.Color}.
     *
     * @param typeMirror The type mirror to test
     * @return True if it represents a subclass of color, false otherwise
     */
    private boolean isColorType(TypeMirror typeMirror) {
        final TypeElement colorType = mProcessingEnv
                .getElementUtils()
                .getTypeElement("android.graphics.Color");

        if (colorType == null) {
            return false;
        } else {
            return mProcessingEnv.getTypeUtils().isSubtype(typeMirror, colorType.asType());
        }
    }
}
