/*
 * 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.ignite.internal.processors.resource;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.managers.deployment.GridDeployment;
import org.apache.ignite.internal.util.GridLeanIdentitySet;
import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.resources.CacheNameResource;
import org.apache.ignite.resources.CacheStoreSessionResource;
import org.apache.ignite.resources.FileSystemResource;
import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.resources.JobContextResource;
import org.apache.ignite.resources.LoadBalancerResource;
import org.apache.ignite.resources.LoggerResource;
import org.apache.ignite.resources.ServiceResource;
import org.apache.ignite.resources.SpringApplicationContextResource;
import org.apache.ignite.resources.SpringResource;
import org.apache.ignite.resources.TaskContinuousMapperResource;
import org.apache.ignite.resources.TaskSessionResource;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Resource container contains caches for classes used for injection.
 * Caches used to improve the efficiency of standard Java reflection mechanism.
 */
public class GridResourceIoc {
    /** Task class resource mapping. Used to efficiently cleanup resources related to class loader. */
    private final ConcurrentMap<ClassLoader, Set<Class<?>>> taskMap = new ConcurrentHashMap<>();

    /** Class descriptors cache. */
    private AtomicReference<Map<Class<?>, ClassDescriptor>> clsDescs = new AtomicReference<>();

    /**
     * @param ldr Class loader.
     */
    void onUndeployed(ClassLoader ldr) {
        Set<Class<?>> clss = taskMap.remove(ldr);

        if (clss != null) {
            Map<Class<?>, ClassDescriptor> newMap, oldMap;

            do {
                oldMap = clsDescs.get();

                if (oldMap == null)
                    break;

                newMap = new HashMap<>(oldMap.size() - clss.size());

                for (Map.Entry<Class<?>, ClassDescriptor> entry : oldMap.entrySet()) {
                    if (!clss.contains(entry.getKey()))
                        newMap.put(entry.getKey(), entry.getValue());
                }
            }
            while (!clsDescs.compareAndSet(oldMap, newMap));
        }
    }

    /**
     * Clears all internal caches.
     */
    void undeployAll() {
        taskMap.clear();

        clsDescs.set(null);
    }

    /**
     * Injects given resource via field or setter with specified annotations on provided target object.
     *
     * @param target Target object.
     * @param annCls Setter annotation.
     * @param injector Resource to inject.
     * @param dep Deployment.
     * @param depCls Deployment class.
     * @return {@code True} if resource was injected.
     * @throws IgniteCheckedException Thrown in case of any errors during injection.
     */
    @SuppressWarnings("SimplifiableIfStatement")
    boolean inject(Object target,
        Class<? extends Annotation> annCls,
        GridResourceInjector injector,
        @Nullable GridDeployment dep,
        @Nullable Class<?> depCls)
        throws IgniteCheckedException {
        return injectInternal(target, annCls, injector, dep, depCls, null);
    }

    /**
     * @param dep Deployment.
     * @param cls Class.
     * @return Descriptor.
     */
    ClassDescriptor descriptor(@Nullable GridDeployment dep, Class<?> cls) {
        Map<Class<?>, ClassDescriptor> newMap, oldMap;
        ClassDescriptor res, newDesc = null;

        do {
            oldMap = clsDescs.get();

            if (oldMap != null && (res = oldMap.get(cls)) != null)
                break;

            if (dep != null) {
                Set<Class<?>> classes = F.addIfAbsent(taskMap, dep.classLoader(), F.<Class<?>>newCSet());

                classes.add(cls);

                dep = null;
            }

            if (oldMap == null)
                newMap = new HashMap<>();
            else
                (newMap = new HashMap<>(oldMap.size() + 1)).putAll(oldMap);

            newMap.put(cls, res = newDesc == null ? (newDesc = new ClassDescriptor(cls)) : newDesc);
        }
        while (!clsDescs.compareAndSet(oldMap, newMap));

        return res;
    }

    /**
     * @param target Target object.
     * @param annCls Setter annotation.
     * @param injector Resource to inject.
     * @param dep Deployment.
     * @param depCls Deployment class.
     * @param checkedObjs Set of already inspected objects to avoid indefinite recursion.
     * @return {@code True} if resource was injected.
     * @throws IgniteCheckedException Thrown in case of any errors during injection.
     */
    private boolean injectInternal(Object target,
        Class<? extends Annotation> annCls,
        GridResourceInjector injector,
        @Nullable GridDeployment dep,
        @Nullable Class<?> depCls,
        @Nullable Set<Object> checkedObjs)
        throws IgniteCheckedException {
        Class<?> targetCls = target.getClass();

        ClassDescriptor descr = descriptor(dep, targetCls);

        T2<GridResourceField[], GridResourceMethod[]> annotatedMembers = descr.annotatedMembers(annCls);

        return descr.injectInternal(target, annCls, annotatedMembers, injector, dep, depCls, checkedObjs);
    }

    /**
     * Checks if annotation is presented on a field or method of the specified object.
     *
     * @param target Target object.
     * @param annCls Annotation class to find on fields or methods of target object.
     * @param dep Deployment.
     * @return {@code true} if annotation is presented, {@code false} if it's not.
     */
    boolean isAnnotationPresent(Object target, Class<? extends Annotation> annCls, @Nullable GridDeployment dep) {
        assert target != null;
        assert annCls != null;

        ClassDescriptor desc = descriptor(dep, target.getClass());

        return desc.recursiveFields().length > 0 || desc.annotatedMembers(annCls) != null;
    }

    /**
     * Checks if annotation is presented on a field or method of the specified object.
     *
     * @param target Target object.
     * @param annSet Annotation classes to find on fields or methods of target object.
     * @param dep Deployment.
     * @return {@code true} if any annotation is presented, {@code false} if it's not.
     */
    boolean isAnnotationsPresent(@Nullable GridDeployment dep, Object target, AnnotationSet annSet) {
        assert target != null;
        assert annSet != null;

        return descriptor(dep, target.getClass()).isAnnotated(annSet) != 0;
    }

    /**
     * Gets set of methods with given annotation.
     *
     * @param dep Deployment.
     * @param cls Class in which search for methods.
     * @param annCls Annotation.
     * @return Set of methods with given annotations.
     */
    GridResourceMethod[] getMethodsWithAnnotation(@Nullable GridDeployment dep, Class<?> cls,
        Class<? extends Annotation> annCls) {
        ClassDescriptor desc = descriptor(dep, cls);

        T2<GridResourceField[], GridResourceMethod[]> t2 = desc.annotatedMembers(annCls);

        return t2 == null ? GridResourceMethod.EMPTY_ARRAY : t2.get2();
    }

    /** Print memory statistics */
    public void printMemoryStats() {
        X.println(">>>   taskMapSize: " + taskMap.size());

        Map<Class<?>, ClassDescriptor> map = clsDescs.get();
        X.println(">>>   classDescriptorsCacheSize: " + (map == null ? 0 : map.size()));
    }

    /**
     *
     */
    class ClassDescriptor {
        /** */
        private final Field[] recursiveFields;

        /** */
        private final Map<Class<? extends Annotation>, T2<GridResourceField[], GridResourceMethod[]>> annMap;

        /**
         * Uses as enum-map with enum {@link AnnotationSet} member as key,
         * and bitmap as a result of matching found annotations with enum set {@link ResourceAnnotation} as value.
         */
        private final int[] containsAnnSets;

        /** Uses as enum-map with enum {@link ResourceAnnotation} member as a keys. */
        private final T2<GridResourceField[], GridResourceMethod[]>[] annArr;

        /**
         * @param cls Class.
         */
        @SuppressWarnings("unchecked")
        ClassDescriptor(Class<?> cls) {
            Map<Class<? extends Annotation>, T2<List<GridResourceField>, List<GridResourceMethod>>> annMap
                = new HashMap<>();

            List<Field> recursiveFieldsList = new ArrayList<>();

            boolean allowImplicitInjection = !GridNoImplicitInjection.class.isAssignableFrom(cls);

            for (Class cls0 = cls; !cls0.equals(Object.class); cls0 = cls0.getSuperclass()) {
                for (Field field : cls0.getDeclaredFields()) {
                    Annotation[] fieldAnns = field.getAnnotations();

                    for (Annotation ann : fieldAnns) {
                        T2<List<GridResourceField>, List<GridResourceMethod>> t2 = annMap.get(ann.annotationType());

                        if (t2 == null) {
                            t2 = new T2<List<GridResourceField>, List<GridResourceMethod>>(
                                new ArrayList<GridResourceField>(),
                                new ArrayList<GridResourceMethod>());

                            annMap.put(ann.annotationType(), t2);
                        }

                        t2.get1().add(new GridResourceField(field, ann));
                    }

                    if (allowImplicitInjection
                        && fieldAnns.length == 0
                        && GridResourceUtils.mayRequireResources(field)) {
                        field.setAccessible(true);

                        // Account for anonymous inner classes.
                        recursiveFieldsList.add(field);
                    }
                }

                for (Method mtd : cls0.getDeclaredMethods()) {
                    for (Annotation ann : mtd.getAnnotations()) {
                        T2<List<GridResourceField>, List<GridResourceMethod>> t2 = annMap.get(ann.annotationType());

                        if (t2 == null) {
                            t2 = new T2<List<GridResourceField>, List<GridResourceMethod>>(
                                new ArrayList<GridResourceField>(),
                                new ArrayList<GridResourceMethod>());

                            annMap.put(ann.annotationType(), t2);
                        }

                        t2.get2().add(new GridResourceMethod(mtd, ann));
                    }
                }
            }

            recursiveFields = recursiveFieldsList.isEmpty() ? U.EMPTY_FIELDS
                : recursiveFieldsList.toArray(new Field[recursiveFieldsList.size()]);

            this.annMap = IgniteUtils.limitedMap(annMap.size());

            for (Map.Entry<Class<? extends Annotation>, T2<List<GridResourceField>, List<GridResourceMethod>>> entry
                : annMap.entrySet()) {
                GridResourceField[] fields = GridResourceField.toArray(entry.getValue().get1());
                GridResourceMethod[] mtds = GridResourceMethod.toArray(entry.getValue().get2());

                this.annMap.put(entry.getKey(), new T2<>(fields, mtds));
            }

            T2<GridResourceField[], GridResourceMethod[]>[] annArr = null;

            if (annMap.isEmpty())
                containsAnnSets = null;
            else {
                int annotationsBits = 0;

                for (ResourceAnnotation ann : ResourceAnnotation.values()) {
                    T2<GridResourceField[], GridResourceMethod[]> member = annotatedMembers(ann.clazz);

                    if (member != null) {
                        if (annArr == null)
                            annArr = new T2[ResourceAnnotation.values().length];

                        annArr[ann.ordinal()] = member;

                        annotationsBits |= 1 << ann.ordinal();
                    }
                }

                AnnotationSet[] annotationSets = AnnotationSet.values();

                containsAnnSets = new int[annotationSets.length];

                for (int i = 0; i < annotationSets.length; i++)
                    containsAnnSets[i] = annotationsBits & annotationSets[i].annotationsBitSet;
            }

            this.annArr = annArr;
        }

        /**
         * @return Recursive fields.
         */
        Field[] recursiveFields() {
            return recursiveFields;
        }

        /**
         * @param annCls Annotation class.
         * @return Fields.
         */
        @Nullable T2<GridResourceField[], GridResourceMethod[]> annotatedMembers(Class<? extends Annotation> annCls) {
            return annMap.get(annCls);
        }

        /**
         * @param set annotation set.
         * @return {@code Bitmask} > 0 if any annotation is presented, otherwise return 0;
         */
        int isAnnotated(AnnotationSet set) {
            return recursiveFields.length > 0 ? set.annotationsBitSet :
                (containsAnnSets == null ? 0 : containsAnnSets[set.ordinal()]);
        }

        /**
         * @param ann Annotation.
         * @return {@code True} if annotation is presented.
         */
        boolean isAnnotated(ResourceAnnotation ann) {
            return recursiveFields.length > 0 || (annArr != null && annArr[ann.ordinal()] != null);
        }

        /**
         * @param target Target object.
         * @param annCls Annotation class.
         * @param annotatedMembers Setter annotation.
         * @param injector Resource to inject.
         * @param dep Deployment.
         * @param depCls Deployment class.
         * @param checkedObjs Set of already inspected objects to avoid indefinite recursion.
         * @return {@code True} if resource was injected.
         * @throws IgniteCheckedException Thrown in case of any errors during injection.
         */
        boolean injectInternal(Object target,
            Class<? extends Annotation> annCls,
            T2<GridResourceField[], GridResourceMethod[]> annotatedMembers,
            GridResourceInjector injector,
            @Nullable GridDeployment dep,
            @Nullable Class<?> depCls,
            @Nullable Set<Object> checkedObjs)
            throws IgniteCheckedException {
            if (recursiveFields.length == 0 && annotatedMembers == null)
                return false;

            if (checkedObjs == null && recursiveFields.length > 0)
                checkedObjs = new GridLeanIdentitySet<>();

            if (checkedObjs != null && !checkedObjs.add(target))
                return false;

            boolean injected = false;

            for (Field field : recursiveFields) {
                try {
                    Object obj = field.get(target);

                    if (obj != null) {
                        assert checkedObjs != null;

                        ClassDescriptor desc = descriptor(dep, obj.getClass());
                        injected |= desc.injectInternal(obj, annCls, desc.annotatedMembers(annCls),
                            injector, dep, depCls, checkedObjs);
                    }
                }
                catch (IllegalAccessException e) {
                    throw new IgniteCheckedException("Failed to inject resource [field=" + field.getName() +
                        ", target=" + target + ']', e);
                }
            }

            if (annotatedMembers != null) {
                for (GridResourceField field : annotatedMembers.get1()) {
                    injector.inject(field, target, depCls, dep);

                    injected = true;
                }

                for (GridResourceMethod mtd : annotatedMembers.get2()) {
                    injector.inject(mtd, target, depCls, dep);

                    injected = true;
                }
            }

            return injected;
        }

        /**
         * @param target Target object.
         * @param ann Setter annotation.
         * @param injector Resource to inject.
         * @param dep Deployment.
         * @param depCls Deployment class.
         * @return {@code True} if resource was injected.
         * @throws IgniteCheckedException Thrown in case of any errors during injection.
         */
        public boolean inject(Object target,
            ResourceAnnotation ann,
            GridResourceInjector injector,
            @Nullable GridDeployment dep,
            @Nullable Class<?> depCls)
            throws IgniteCheckedException {
            return injectInternal(target,
                ann.clazz,
                annArr == null ? null : annArr[ann.ordinal()],
                injector,
                dep,
                depCls,
                null);
        }
    }

    /**
     *
     */
    enum ResourceAnnotation {
        /** */
        CACHE_NAME(CacheNameResource.class),

        /** */
        SPRING_APPLICATION_CONTEXT(SpringApplicationContextResource.class),

        /** */
        SPRING(SpringResource.class),

        /** */
        IGNITE_INSTANCE(IgniteInstanceResource.class),

        /** */
        LOGGER(LoggerResource.class),

        /** */
        SERVICE(ServiceResource.class),

        /** */
        TASK_SESSION(TaskSessionResource.class),

        /** */
        LOAD_BALANCER(LoadBalancerResource.class),

        /** */
        TASK_CONTINUOUS_MAPPER(TaskContinuousMapperResource.class),

        /** */
        JOB_CONTEXT(JobContextResource.class),

        /** */
        CACHE_STORE_SESSION(CacheStoreSessionResource.class),

        /** */
        FILESYSTEM_RESOURCE(FileSystemResource.class);

        /** */
        public final Class<? extends Annotation> clazz;

        /**
         * @param clazz annotation class.
         */
        ResourceAnnotation(Class<? extends Annotation> clazz) {
            this.clazz = clazz;
        }
    }

    /**
     *
     */
    public enum AnnotationSet {
        /** */
        GENERIC(
            ResourceAnnotation.SPRING_APPLICATION_CONTEXT,
            ResourceAnnotation.SPRING,
            ResourceAnnotation.IGNITE_INSTANCE,
            ResourceAnnotation.LOGGER,
            ResourceAnnotation.SERVICE
        ),

        /** */
        ENTRY_PROCESSOR(
            ResourceAnnotation.CACHE_NAME,

            ResourceAnnotation.SPRING_APPLICATION_CONTEXT,
            ResourceAnnotation.SPRING,
            ResourceAnnotation.IGNITE_INSTANCE,
            ResourceAnnotation.LOGGER,
            ResourceAnnotation.SERVICE
        ),

        /** */
        TASK(
            ResourceAnnotation.TASK_SESSION,
            ResourceAnnotation.LOAD_BALANCER,
            ResourceAnnotation.TASK_CONTINUOUS_MAPPER,

            ResourceAnnotation.SPRING_APPLICATION_CONTEXT,
            ResourceAnnotation.SPRING,
            ResourceAnnotation.IGNITE_INSTANCE,
            ResourceAnnotation.LOGGER,
            ResourceAnnotation.SERVICE
        ),

        /** */
        JOB(
            ResourceAnnotation.TASK_SESSION,
            ResourceAnnotation.JOB_CONTEXT,

            ResourceAnnotation.SPRING_APPLICATION_CONTEXT,
            ResourceAnnotation.SPRING,
            ResourceAnnotation.IGNITE_INSTANCE,
            ResourceAnnotation.LOGGER,
            ResourceAnnotation.SERVICE
        );

        /** Resource annotations bits for fast checks. */
        public final int annotationsBitSet;

        /** Holds annotations in order */
        public final ResourceAnnotation[] annotations;

        /**
         * @param annotations ResourceAnnotations.
         */
        AnnotationSet(ResourceAnnotation... annotations) {
            assert annotations.length < 32 : annotations.length;

            this.annotations = annotations;

            int mask = 0;

            for (ResourceAnnotation ann : annotations)
                mask |= 1 << ann.ordinal();

            annotationsBitSet = mask;
        }
    }
}
