/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.bval.jsr;

import org.apache.bval.model.Features;
import org.apache.bval.model.Meta;
import org.apache.bval.model.MetaBean;
import org.apache.bval.util.AccessStrategy;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.Valid;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import javax.validation.constraintvalidation.ValidationTarget;
import javax.validation.groups.ConvertGroup;
import javax.validation.groups.Default;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;

/**
 * Description: implements uniform handling of JSR303 {@link Constraint}
 * annotations, including composed constraints and the resolution of
 * {@link ConstraintValidator} implementations.
 */
@Privilizing(@CallTo(Reflection.class))
public final class AnnotationProcessor {
    /** {@link ApacheFactoryContext} used */
    private final ApacheValidatorFactory factory;

    /**
     * Create a new {@link AnnotationProcessor} instance.
     * 
     * @param factory the validator factory.
     */
    public AnnotationProcessor(ApacheValidatorFactory factory) {
        this.factory = factory;
    }

    /**
     * Process JSR303 annotations.
     * 
     * @param prop
     *            potentially null
     * @param owner
     *            bean type
     * @param element
     *            whose annotations to read
     * @param access
     *            strategy for <code>prop</code>
     * @param appender
     *            handling accumulation
     * @return whether any processing took place
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public boolean processAnnotations(Meta prop, Class<?> owner, AnnotatedElement element, AccessStrategy access,
        AppendValidation appender) throws IllegalAccessException, InvocationTargetException {

        boolean changed = false;
        for (final Annotation annotation : element.getDeclaredAnnotations()) {
            final Class<?> type = annotation.annotationType();
            if (type.getName().startsWith("java.lang.annotation.")) {
                continue;
            }
            changed = processAnnotation(annotation, prop, owner, access, appender, true) || changed;
        }
        return changed;
    }

    /**
     * Process a single annotation.
     * 
     * @param <A>
     *            annotation type
     * @param annotation
     *            to process
     * @param prop
     *            potentially null
     * @param owner
     *            bean type
     * @param access
     *            strategy for <code>prop</code>
     * @param appender
     *            handling accumulation
     * @return whether any processing took place
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public <A extends Annotation> boolean processAnnotation(A annotation, Meta prop, Class<?> owner,
            AccessStrategy access, AppendValidation appender, boolean reflection) throws IllegalAccessException,
        InvocationTargetException {
        if (annotation instanceof Valid) {
            return addAccessStrategy(prop, access);
        }

        if (ConvertGroup.class.isInstance(annotation) || ConvertGroup.List.class.isInstance(annotation)) {
            if (!reflection) {
                Collection<Annotation> annotations = prop.getFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS);
                if (annotations == null) {
                    annotations = new ArrayList<Annotation>();
                    prop.putFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS, annotations);
                }
                annotations.add(annotation);
            }
            return true;
        }

        /**
         * An annotation is considered a constraint definition if its retention
         * policy contains RUNTIME and if the annotation itself is annotated
         * with javax.validation.Constraint.
         */
        final Constraint vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
        if (vcAnno != null) {
            Class<? extends ConstraintValidator<A, ?>>[] validatorClasses;
            validatorClasses = findConstraintValidatorClasses(annotation, vcAnno);
            return applyConstraint(annotation, validatorClasses, prop, owner, access, appender);
        }
        /**
         * Multi-valued constraints: To support this requirement, the bean
         * validation provider treats regular annotations (annotations not
         * annotated by @Constraint) whose value element has a return type of an
         * array of constraint annotations in a special way.
         */
        final Object result =
            Reflection.getAnnotationValue(annotation, ConstraintAnnotationAttributes.VALUE.getAttributeName());
        if (result instanceof Annotation[]) {
            boolean changed = false;
            for (final Annotation each : (Annotation[]) result) {
                if (each.annotationType().getName().startsWith("java.lang.annotation")) {
                    continue;
                }

                changed |= processAnnotation(each, prop, owner, access, appender, reflection);
            }
            return changed;
        }
        return false;
    }

    /**
     * Add the specified {@link AccessStrategy} to <code>prop</code>; noop if
     * <code>prop == null</code>.
     * 
     * @param prop
     * @param access
     * @return whether anything took place.
     */
    public boolean addAccessStrategy(Meta prop, AccessStrategy access) {
        if (prop == null) {
            return false;
        }
        AccessStrategy[] strategies = prop.getFeature(Features.Property.REF_CASCADE);
        if (ArrayUtils.contains(strategies, access)) {
            return false;
        }
        if (strategies == null) {
            strategies = new AccessStrategy[] { access };
        } else {
            strategies = ArrayUtils.add(strategies, access);
        }
        prop.putFeature(Features.Property.REF_CASCADE, strategies);
        return true;
    }

    /**
     * Find available {@link ConstraintValidation} classes for a given
     * constraint annotation.
     * 
     * @param annotation
     * @param vcAnno
     * @return {@link ConstraintValidation} implementation class array
     */
    @SuppressWarnings("unchecked")
    private <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] findConstraintValidatorClasses(
        A annotation, Constraint vcAnno) {
        if (vcAnno == null) {
            vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
        }
        final Class<A> annotationType = (Class<A>) annotation.annotationType();
        Class<? extends ConstraintValidator<A, ?>>[] validatorClasses =
            factory.getConstraintsCache().getConstraintValidators(annotationType);
        if (validatorClasses == null) {
            validatorClasses = (Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy();
            if (validatorClasses.length == 0) {
                validatorClasses = factory.getDefaultConstraints().getValidatorClasses(annotationType);
            }
        }
        return validatorClasses;
    }

    /**
     * Apply a constraint to the specified <code>appender</code>.
     * 
     * @param annotation
     *            constraint annotation
     * @param rawConstraintClasses
     *            known {@link ConstraintValidator} implementation classes for
     *            <code>annotation</code>
     * @param prop
     *            meta-property
     * @param owner
     *            type
     * @param access
     *            strategy
     * @param appender
     * @return success flag
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private <A extends Annotation> boolean applyConstraint(
        A annotation,
        Class<? extends ConstraintValidator<A, ?>>[] rawConstraintClasses, Meta prop, Class<?> owner,
        AccessStrategy access, AppendValidation appender) throws IllegalAccessException, InvocationTargetException {

        final Class<? extends ConstraintValidator<A, ?>>[] constraintClasses = select(rawConstraintClasses, access);
        if (constraintClasses != null && constraintClasses.length == 0 && rawConstraintClasses.length > 0) {
            return false;
        }

        final AnnotationConstraintBuilder<A> builder =
            new AnnotationConstraintBuilder<A>(
                constraintClasses,
                annotation, owner, access, null);

        // JSR-303 3.4.4: Add implicit groups
        if (prop != null && prop.getParentMetaBean() != null) {
            final MetaBean parentMetaBean = prop.getParentMetaBean();
            // If:
            // - the owner is an interface
            // - the class of the metabean being build is different than the
            // owner
            // - and only the Default group is defined
            // Then: add the owner interface as implicit groups
            if (builder.getConstraintValidation().getOwner().isInterface()
                && parentMetaBean.getBeanClass() != builder.getConstraintValidation().getOwner()
                && builder.getConstraintValidation().getGroups().size() == 1
                && builder.getConstraintValidation().getGroups().contains(Default.class)) {
                Set<Class<?>> groups = builder.getConstraintValidation().getGroups();
                groups.add(builder.getConstraintValidation().getOwner());
                builder.getConstraintValidation().setGroups(groups);
            }
        }

        // If already building a constraint composition tree, ensure that:
        // - the parent groups are inherited
        // - the parent payload is inherited
        if (appender instanceof AppendValidationToBuilder) {
            AppendValidationToBuilder avb = (AppendValidationToBuilder) appender;
            builder.getConstraintValidation().setGroups(avb.getInheritedGroups());
            builder.getConstraintValidation().setPayload(avb.getInheritedPayload());
        }

        // process composed constraints:
        // here are not other superclasses possible, because annotations do not
        // inherit!
        processAnnotations(prop, owner, annotation.annotationType(), access, new AppendValidationToBuilder(builder));

        // Even if the validator is null, it must be added to mimic the RI impl
        appender.append(builder.getConstraintValidation());
        return true;
    }

    private static <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] select(
        final Class<? extends ConstraintValidator<A, ?>>[] rawConstraintClasses, final AccessStrategy access) {
        final boolean isReturn = ReturnAccess.class.isInstance(access);
        final boolean isParam = ParametersAccess.class.isInstance(access);
        if (rawConstraintClasses != null && (isReturn || isParam)) {
            final Collection<Class<? extends ConstraintValidator<A, ?>>> selected =
                new ArrayList<Class<? extends ConstraintValidator<A, ?>>>();
            for (final Class<? extends ConstraintValidator<A, ?>> constraint : rawConstraintClasses) {
                final SupportedValidationTarget target = constraint.getAnnotation(SupportedValidationTarget.class);
                if (target == null && isReturn) {
                    selected.add(constraint);
                } else if (target != null) {
                    for (final ValidationTarget validationTarget : target.value()) {
                        if (isReturn && ValidationTarget.ANNOTATED_ELEMENT == validationTarget) {
                            selected.add(constraint);
                        } else if (isParam && ValidationTarget.PARAMETERS == validationTarget) {
                            selected.add(constraint);
                        }
                    }
                }
            }
            @SuppressWarnings("unchecked")
            final Class<? extends ConstraintValidator<A, ?>>[] result = selected.toArray(new Class[selected.size()]);
            return result;
        }
        return rawConstraintClasses;
    }

}
