/*
 * 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.sling.models.impl.model;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.inject.Named;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.Required;
import org.apache.sling.models.annotations.Source;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.ViaProviderType;
import org.apache.sling.models.annotations.via.BeanProperty;
import org.apache.sling.models.impl.ModelAdapterFactory;
import org.apache.sling.models.impl.ReflectionUtil;
import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("deprecation")
abstract class AbstractInjectableElement implements InjectableElement {

    private final AnnotatedElement element;
    private final Type type;
    private final String name;
    private final String source;
    private final ViaSpec via;
    private final boolean hasDefaultValue;
    private final Object defaultValue;
    private final boolean isOptional;
    private final boolean isRequired;
    private final DefaultInjectionStrategy injectionStrategy;
    private final DefaultInjectionStrategy defaultInjectionStrategy;

    private static final Logger log = LoggerFactory.getLogger(ModelAdapterFactory.class);

    public AbstractInjectableElement(AnnotatedElement element, Type type, String defaultName,
            StaticInjectAnnotationProcessorFactory[] processorFactories, DefaultInjectionStrategy defaultInjectionStrategy) {
        this.element = element;
        this.type = type;
        InjectAnnotationProcessor2 annotationProcessor = getAnnotationProcessor(element, processorFactories);
        this.name = getName(element, defaultName, annotationProcessor);
        this.source = getSource(element);
        this.via = getVia(element, annotationProcessor);
        this.hasDefaultValue = getHasDefaultValue(element, annotationProcessor);
        this.defaultValue = getDefaultValue(element, type, annotationProcessor);
        this.isOptional = getOptional(element, annotationProcessor);
        this.isRequired = getRequired(element, annotationProcessor);
        this.injectionStrategy = getInjectionStrategy(element, annotationProcessor, defaultInjectionStrategy);
        this.defaultInjectionStrategy = defaultInjectionStrategy;
    }

    private static InjectAnnotationProcessor2 getAnnotationProcessor(AnnotatedElement element, StaticInjectAnnotationProcessorFactory[] processorFactories) {
        for (StaticInjectAnnotationProcessorFactory processorFactory : processorFactories) {
            InjectAnnotationProcessor2 annotationProcessor = processorFactory.createAnnotationProcessor(element);
            if (annotationProcessor != null) {
                return annotationProcessor;
            }
        }
        return null;
    }

    @SuppressWarnings("unused")
    private static String getName(AnnotatedElement element, String defaultName, InjectAnnotationProcessor2 annotationProcessor) {
        String name = null;
        if (annotationProcessor != null) {
            name = annotationProcessor.getName();
        }
        if (name == null) {
            Named namedAnnotation = element.getAnnotation(Named.class);
            if (namedAnnotation != null) {
                name = namedAnnotation.value();
            }
            else {
                name = defaultName;
            }
        }
        return name;
    }

    @SuppressWarnings("unused")
    private static String getSource(AnnotatedElement element) {
        Source source = ReflectionUtil.getAnnotation(element, Source.class);
        if (source != null) {
            return source.value();
        }
        return null;
    }

    private static ViaSpec getVia(AnnotatedElement element, InjectAnnotationProcessor2 annotationProcessor) {
        ViaSpec spec = new ViaSpec();
        if (annotationProcessor != null) {
            spec.via = annotationProcessor.getVia();
        }
        if (spec.via == null) {
            Via viaAnnotation = element.getAnnotation(Via.class);
            if (viaAnnotation != null) {
                spec.via = viaAnnotation.value();
                spec.type = viaAnnotation.type();
            }
        } else {
            // use default type
            spec.type = BeanProperty.class;
        }
        return spec;
    }

    private static boolean getHasDefaultValue(AnnotatedElement element, InjectAnnotationProcessor2 annotationProcessor) {
        if (annotationProcessor != null) {
            return annotationProcessor.hasDefault();
        }
        return element.isAnnotationPresent(Default.class);
    }

    @SuppressWarnings("unused")
    private static Object getDefaultValue(AnnotatedElement element, Type type, InjectAnnotationProcessor2 annotationProcessor) {
        if (annotationProcessor != null && annotationProcessor.hasDefault()) {
            return annotationProcessor.getDefault();
        }

        Default defaultAnnotation = element.getAnnotation(Default.class);
        if (defaultAnnotation == null) {
            return null;
        }

        Object value = null;

        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Type rawType = parameterizedType.getRawType();
            if ((rawType == Collection.class || rawType == List.class)
                    && parameterizedType.getActualTypeArguments().length > 0) {
                Type itemType = parameterizedType.getActualTypeArguments()[0];
                if (itemType == String.class) {
                    value = arrayToTypedList(defaultAnnotation.values());
                } else if (itemType == Integer.class) {
                    value = arrayToTypedList(defaultAnnotation.intValues());
                } else if (itemType == Long.class) {
                    value = arrayToTypedList(defaultAnnotation.longValues());
                } else if (itemType == Boolean.class) {
                    value = arrayToTypedList(defaultAnnotation.booleanValues());
                } else if (itemType == Short.class) {
                    value = arrayToTypedList(defaultAnnotation.shortValues());
                } else if (itemType == Float.class) {
                    value = arrayToTypedList(defaultAnnotation.floatValues());
                } else if (itemType == Double.class) {
                    value = arrayToTypedList(defaultAnnotation.doubleValues());
                } else {
                    log.warn("Default values for {} List/Collection are not supported", itemType);
                }
            }
            else {
                log.warn("Cannot provide default for {}", type);
            }
        }
        else if (type instanceof Class) {
            Class<?> injectedClass = (Class<?>) type;
            if (injectedClass.isArray()) {
                Class<?> componentType = injectedClass.getComponentType();
                if (componentType == String.class) {
                    value = defaultAnnotation.values();
                } else if (componentType == Integer.TYPE) {
                    value = defaultAnnotation.intValues();
                } else if (componentType == Integer.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.intValues());
                } else if (componentType == Long.TYPE) {
                    value = defaultAnnotation.longValues();
                } else if (componentType == Long.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.longValues());
                } else if (componentType == Boolean.TYPE) {
                    value = defaultAnnotation.booleanValues();
                } else if (componentType == Boolean.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.booleanValues());
                } else if (componentType == Short.TYPE) {
                    value = defaultAnnotation.shortValues();
                } else if (componentType == Short.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.shortValues());
                } else if (componentType == Float.TYPE) {
                    value = defaultAnnotation.floatValues();
                } else if (componentType == Float.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.floatValues());
                } else if (componentType == Double.TYPE) {
                    value = defaultAnnotation.doubleValues();
                } else if (componentType == Double.class) {
                    value = ArrayUtils.toObject(defaultAnnotation.doubleValues());
                } else {
                    log.warn("Default values for {} are not supported", componentType);
                }
            } else {
                if (injectedClass == String.class) {
                    value = defaultAnnotation.values().length == 0 ? "" : defaultAnnotation.values()[0];
                } else if (injectedClass == Integer.class) {
                    value = defaultAnnotation.intValues().length == 0 ? 0 : defaultAnnotation.intValues()[0];
                } else if (injectedClass == Long.class) {
                    value = defaultAnnotation.longValues().length == 0 ? 0l : defaultAnnotation.longValues()[0];
                } else if (injectedClass == Boolean.class) {
                    value = defaultAnnotation.booleanValues().length == 0 ? false : defaultAnnotation.booleanValues()[0];
                } else if (injectedClass == Short.class) {
                    value = defaultAnnotation.shortValues().length == 0 ? ((short) 0) : defaultAnnotation.shortValues()[0];
                } else if (injectedClass == Float.class) {
                    value = defaultAnnotation.floatValues().length == 0 ? 0f : defaultAnnotation.floatValues()[0];
                } else if (injectedClass == Double.class) {
                    value = defaultAnnotation.doubleValues().length == 0 ? 0d : defaultAnnotation.doubleValues()[0];
                } else {
                    log.warn("Default values for {} are not supported", injectedClass);
                }
            }
        } else {
            log.warn("Cannot provide default for {}", type);
        }
        return value;
    }

    /**
     * Converts array to typed list of values.
     * @param <T> Array/List type
     * @param array Array
     * @return Typed list or null if array is empty
     */
    @SuppressWarnings("unchecked")
    private static <T> @Nullable List<T> arrayToTypedList(Object array) {
        if (array != null && array.getClass().isArray()) {
            int arrayLength = Array.getLength(array);
            if (arrayLength > 0) {
                List<T> result = new ArrayList<>();
                for (int i=0; i<arrayLength; i++) {
                    result.add((T)Array.get(array, i));
                }
                return result;
            }

        }
        return null;
    }

    private static boolean getOptional(AnnotatedElement element, InjectAnnotationProcessor annotationProcessor) {
        if (element.isAnnotationPresent(Optional.class)) {
            return true;
        }
        if (annotationProcessor != null) {
            Boolean optional = annotationProcessor.isOptional();
            if (optional != null) {
                return optional.booleanValue();
            }
        }
        return false;
    }

    private static boolean getRequired(AnnotatedElement element, InjectAnnotationProcessor annotationProcessor) {
        // do not evaluate the injector-specific annotation (those are only considered for optional)
        // even setting optional=false will not make an attribute mandatory
        return element.isAnnotationPresent(Required.class);
    }

    private static DefaultInjectionStrategy getInjectionStrategy(AnnotatedElement element, InjectAnnotationProcessor annotationProcessor, DefaultInjectionStrategy defaultInjectionStrategy) {
        if (annotationProcessor != null) {
            if (annotationProcessor instanceof InjectAnnotationProcessor2) {
                switch (((InjectAnnotationProcessor2)annotationProcessor).getInjectionStrategy()) {
                    case OPTIONAL:
                        return DefaultInjectionStrategy.OPTIONAL;
                    case REQUIRED:
                        return DefaultInjectionStrategy.REQUIRED;
                    case DEFAULT:
                        break;
                }
            }
        }
        return defaultInjectionStrategy;
    }

    @Override
    public final AnnotatedElement getAnnotatedElement() {
        return this.element;
    }

    @Override
    public final Type getType() {
        return type;
    }

    @Override
    public final String getName() {
        return this.name;
    }

    @Override
    public String getSource() {
        return this.source;
    }

    @Override
    public String getVia() {
        return this.via.via;
    }

    @Override
    public Class<? extends ViaProviderType> getViaProviderType() { return this.via.type; }

    @Override
    public boolean hasDefaultValue() {
        return this.hasDefaultValue;
    }

    @Override
    public Object getDefaultValue() {
        return this.defaultValue;
    }

    @Override
    public boolean isOptional(InjectAnnotationProcessor annotationProcessor) {
        DefaultInjectionStrategy injectionStrategy = this.injectionStrategy;
        boolean isOptional = this.isOptional;
        boolean isRequired = this.isRequired;

        // evaluate annotationProcessor (which depends on the adapter)
        if (annotationProcessor != null) {
            isOptional = getOptional(getAnnotatedElement(), annotationProcessor);
            isRequired = getRequired(getAnnotatedElement(), annotationProcessor);
            injectionStrategy = getInjectionStrategy(element, annotationProcessor, defaultInjectionStrategy);
        }
        if (injectionStrategy == DefaultInjectionStrategy.REQUIRED) {
            return isOptional;
        } else {
            return !isRequired;
        }
    }

    private static class ViaSpec {
        String via;
        Class<? extends ViaProviderType> type;
    }

}
