/*
 * 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.MetaBeanFactory;
import org.apache.bval.jsr.groups.Group;
import org.apache.bval.jsr.util.ClassHelper;
import org.apache.bval.jsr.xml.MetaConstraint;
import org.apache.bval.model.Meta;
import org.apache.bval.model.MetaBean;
import org.apache.bval.model.MetaConstructor;
import org.apache.bval.model.MetaMethod;
import org.apache.bval.model.MetaParameter;
import org.apache.bval.model.MetaProperty;
import org.apache.bval.util.AccessStrategy;
import org.apache.bval.util.FieldAccess;
import org.apache.bval.util.MethodAccess;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;

import javax.validation.ConstraintDeclarationException;
import javax.validation.GroupDefinitionException;
import javax.validation.GroupSequence;
import javax.validation.groups.ConvertGroup;
import javax.validation.groups.Default;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Description: process the class annotations for JSR303 constraint validations to build the MetaBean with information
 * from annotations and JSR303 constraint mappings (defined in xml)<br/>
 */
@Privilizing(@CallTo(Reflection.class))
public class JsrMetaBeanFactory implements MetaBeanFactory {
    /** Shared log instance */
    // of dubious utility as it's static :/
    protected static final Logger log = Logger.getLogger(JsrMetaBeanFactory.class.getName());

    /** {@link javax.validation.ValidatorFactory} used */
    protected final ApacheValidatorFactory factory;

    /**
     * {@link AnnotationProcessor} used.
     */
    protected AnnotationProcessor annotationProcessor;

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

    /**
     * {@inheritDoc} Add the validation features to the metabean that come from JSR303 annotations in the beanClass.
     */
    public void buildMetaBean(MetaBean metabean) {
        try {
            final Class<?> beanClass = metabean.getBeanClass();
            processGroupSequence(beanClass, metabean);

            // process class, superclasses and interfaces
            final List<Class<?>> classSequence =
                ClassHelper.fillFullClassHierarchyAsList(new ArrayList<Class<?>>(), beanClass);

            // start with superclasses and go down the hierarchy so that
            // the child classes are processed last to have the chance to
            // overwrite some declarations
            // of their superclasses and that they see what they inherit at the
            // time of processing
            for (int i = classSequence.size() - 1; i >= 0; i--) {
                Class<?> eachClass = classSequence.get(i);
                processClass(eachClass, metabean);
                processGroupSequence(eachClass, metabean, "{GroupSequence:" + eachClass.getCanonicalName() + "}");
            }

        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException(e);
        } catch (InvocationTargetException e) {
            throw new IllegalArgumentException(e.getTargetException());
        }
    }

    /**
     * Process class annotations, field and method annotations.
     * 
     * @param beanClass
     * @param metabean
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void processClass(Class<?> beanClass, MetaBean metabean) throws IllegalAccessException,
        InvocationTargetException {

        // if NOT ignore class level annotations
        if (!factory.getAnnotationIgnores().isIgnoreAnnotations(beanClass)) {
            annotationProcessor.processAnnotations(null, beanClass, beanClass, null, new AppendValidationToMeta(metabean));
        }

        final Collection<String> missingValid = new ArrayList<String>();

        final Field[] fields = Reflection.getDeclaredFields(beanClass);
        for (final Field field : fields) {
            MetaProperty metaProperty = metabean.getProperty(field.getName());
            // create a property for those fields for which there is not yet a
            // MetaProperty
            if (!factory.getAnnotationIgnores().isIgnoreAnnotations(field)) {
                AccessStrategy access = new FieldAccess(field);
                boolean create = metaProperty == null;
                if (create) {
                    metaProperty = addMetaProperty(metabean, access);
                }
                if (!annotationProcessor.processAnnotations(metaProperty, beanClass, field, access,
                    new AppendValidationToMeta(metaProperty)) && create) {
                    metabean.putProperty(metaProperty.getName(), null);
                }

                if (field.getAnnotation(ConvertGroup.class) != null) {
                    missingValid.add(field.getName());
                }
            }
        }
        final Method[] methods = Reflection.getDeclaredMethods(beanClass);
        for (final Method method : methods) {
            if (method.isSynthetic() || method.isBridge()) {
                continue;
            }
            String propName = null;
            if (method.getParameterTypes().length == 0) {
                propName = MethodAccess.getPropertyName(method);
            }
            if (propName != null) {
                if (!factory.getAnnotationIgnores().isIgnoreAnnotations(method)) {
                    AccessStrategy access = new MethodAccess(propName, method);
                    MetaProperty metaProperty = metabean.getProperty(propName);
                    boolean create = metaProperty == null;
                    // create a property for those methods for which there is
                    // not yet a MetaProperty
                    if (create) {
                        metaProperty = addMetaProperty(metabean, access);
                    }
                    if (!annotationProcessor.processAnnotations(metaProperty, beanClass, method, access,
                        new AppendValidationToMeta(metaProperty)) && create) {
                        metabean.putProperty(propName, null);
                    }
                }
            }
        }

        addXmlConstraints(beanClass, metabean);

        for (final String name : missingValid) {
            final MetaProperty metaProperty = metabean.getProperty(name);
            if (metaProperty != null && metaProperty.getFeature(JsrFeatures.Property.REF_CASCADE) == null) {
                throw new ConstraintDeclarationException("@ConvertGroup needs @Valid");
            }
        }
        missingValid.clear();
    }

    /**
     * Add cascade validation and constraints from xml mappings
     * 
     * @param beanClass
     * @param metabean
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void addXmlConstraints(Class<?> beanClass, MetaBean metabean) throws IllegalAccessException,
        InvocationTargetException {
        for (final MetaConstraint<?, ? extends Annotation> metaConstraint : factory.getMetaConstraints(beanClass)) {
            Meta meta;
            AccessStrategy access = metaConstraint.getAccessStrategy();
            boolean create = false;
            if (access == null) { // class level
                meta = null;
            } else if (access.getElementType() == ElementType.METHOD && !metaConstraint.getMember().getName().startsWith("get")) { // TODO: better getter test
                final Method method = Method.class.cast(metaConstraint.getMember());
                meta = metabean.getMethod(method);
                final MetaMethod metaMethod;
                if (meta == null) {
                    meta = new MetaMethod(metabean, method);
                    metaMethod = MetaMethod.class.cast(meta);
                    metabean.addMethod(method, metaMethod);
                } else {
                    metaMethod = MetaMethod.class.cast(meta);
                }
                final Integer index = metaConstraint.getIndex();
                if (index != null && index >= 0) {
                    MetaParameter param = metaMethod.getParameter(index);
                    if (param == null) {
                        param = new MetaParameter(metaMethod, index);
                        metaMethod.addParameter(index, param);
                    }
                    param.addAnnotation(metaConstraint.getAnnotation());
                } else {
                    metaMethod.addAnnotation(metaConstraint.getAnnotation());
                }
                continue;
            } else if (access.getElementType() == ElementType.CONSTRUCTOR){
                final Constructor<?> constructor = Constructor.class.cast(metaConstraint.getMember());
                meta = metabean.getConstructor(constructor);
                final MetaConstructor metaConstructor;
                if (meta == null) {
                    meta = new MetaConstructor(metabean, constructor);
                    metaConstructor = MetaConstructor.class.cast(meta);
                    metabean.addConstructor(constructor, metaConstructor);
                } else {
                    metaConstructor = MetaConstructor.class.cast(meta);
                }
                final Integer index = metaConstraint.getIndex();
                if (index != null && index >= 0) {
                    MetaParameter param = metaConstructor.getParameter(index);
                    if (param == null) {
                        param = new MetaParameter(metaConstructor, index);
                        metaConstructor.addParameter(index, param);
                    }
                    param.addAnnotation(metaConstraint.getAnnotation());
                } else {
                    metaConstructor.addAnnotation(metaConstraint.getAnnotation());
                }
                continue;
            } else { // property level
                meta = metabean.getProperty(access.getPropertyName());
                create = meta == null;
                if (create) {
                    meta = addMetaProperty(metabean, access);
                }
            }
            if (!annotationProcessor.processAnnotation(metaConstraint.getAnnotation(), meta, beanClass,
                metaConstraint.getAccessStrategy(), new AppendValidationToMeta(meta == null ? metabean : meta), false)
                && create) {
                metabean.putProperty(access.getPropertyName(), null);
            }
        }
        for (final AccessStrategy access : factory.getValidAccesses(beanClass)) {
            if (access.getElementType() == ElementType.PARAMETER) {
                continue;
            }

            MetaProperty metaProperty = metabean.getProperty(access.getPropertyName());
            boolean create = metaProperty == null;
            if (create) {
                metaProperty = addMetaProperty(metabean, access);
            }
            if (!annotationProcessor.addAccessStrategy(metaProperty, access) && create) {
                metabean.putProperty(access.getPropertyName(), null);
            }
        }
    }

    private void processGroupSequence(Class<?> beanClass, MetaBean metabean) {
        processGroupSequence(beanClass, metabean, JsrFeatures.Bean.GROUP_SEQUENCE);
    }

    private void processGroupSequence(Class<?> beanClass, MetaBean metabean, String key) {
        GroupSequence annotation = beanClass.getAnnotation(GroupSequence.class);
        List<Group> groupSeq = metabean.getFeature(key);
        if (groupSeq == null) {
            groupSeq = metabean.initFeature(key, new ArrayList<Group>(annotation == null ? 1 : annotation.value().length));
        }
        Class<?>[] groupClasses = factory.getDefaultSequence(beanClass);
        if (groupClasses == null || groupClasses.length == 0) {
            if (annotation == null) {
                groupSeq.add(Group.DEFAULT);
                return;
            } else {
                groupClasses = annotation.value();
            }
        }
        boolean containsDefault = false;
        for (final Class<?> groupClass : groupClasses) {
            if (groupClass.getName().equals(beanClass.getName())) {
                groupSeq.add(Group.DEFAULT);
                containsDefault = true;
            } else if (groupClass.getName().equals(Default.class.getName())) {
                throw new GroupDefinitionException("'Default.class' must not appear in @GroupSequence! Use '"
                    + beanClass.getSimpleName() + ".class' instead.");
            } else {
                groupSeq.add(new Group(groupClass));
            }
        }
        if (!containsDefault) {
            throw new GroupDefinitionException("Redefined default group sequence must contain " + beanClass.getName());
        }
        log.log(Level.FINEST, String.format("Default group sequence for bean %s is: %s", beanClass.getName(), groupSeq));
    }

    /**
     * Add a {@link MetaProperty} to a {@link MetaBean}.
     * @param parentMetaBean
     * @param access
     * @return the created {@link MetaProperty}
     */
    public static MetaProperty addMetaProperty(MetaBean parentMetaBean, AccessStrategy access) {
        final MetaProperty result = new MetaProperty();
        final String name = access.getPropertyName();
        result.setName(name);
        result.setType(access.getJavaType());
        parentMetaBean.putProperty(name, result);
        return result;
    }
}
