/*
 * 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.commons.jcs3.jcache.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;

import javax.annotation.PreDestroy;
import javax.cache.annotation.CacheDefaults;
import javax.cache.annotation.CacheKey;
import javax.cache.annotation.CacheKeyGenerator;
import javax.cache.annotation.CachePut;
import javax.cache.annotation.CacheRemove;
import javax.cache.annotation.CacheRemoveAll;
import javax.cache.annotation.CacheResolverFactory;
import javax.cache.annotation.CacheResult;
import javax.cache.annotation.CacheValue;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.interceptor.InvocationContext;

@ApplicationScoped
public class CDIJCacheHelper
{
    private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName());
    private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.commons.jcs3.jcache.cdi.skip-close");

    private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed
    private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl();

    private final Collection<CreationalContext<?>> toRelease = new ArrayList<>();
    private final ConcurrentMap<MethodKey, MethodMeta> methods = new ConcurrentHashMap<>();

    @Inject
    private BeanManager beanManager;

    @PreDestroy
    private void release() {
        if (CLOSE_CACHE && defaultCacheResolverFactory != null)
        {
            defaultCacheResolverFactory.release();
        }
        for (final CreationalContext<?> cc : toRelease)
        {
            try
            {
                cc.release();
            }
            catch (final RuntimeException re)
            {
                LOGGER.warning(re.getMessage());
            }
        }
    }

    public MethodMeta findMeta(final InvocationContext ic)
    {
        final Method mtd = ic.getMethod();
        final Class<?> refType = findKeyType(ic.getTarget());
        final MethodKey key = new MethodKey(refType, mtd);
        MethodMeta methodMeta = methods.get(key);
        if (methodMeta == null)
        {
            synchronized (this)
            {
                methodMeta = methods.get(key);
                if (methodMeta == null)
                {
                    methodMeta = createMeta(ic);
                    methods.put(key, methodMeta);
                }
            }
        }
        return methodMeta;
    }

    private Class<?> findKeyType(final Object target)
    {
        if (null == target)
        {
            return null;
        }
        return target.getClass();
    }

    // it is unlikely we have all annotations but for now we have a single meta model
    private MethodMeta createMeta(final InvocationContext ic)
    {
        final CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget()
                                                      .getClass(), ic.getMethod());

        final Class<?>[] parameterTypes = ic.getMethod().getParameterTypes();
        final Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations();
        final List<Set<Annotation>> annotations = new ArrayList<>();
        for (final Annotation[] parameterAnnotation : parameterAnnotations)
        {
            final Set<Annotation> set = new HashSet<>(parameterAnnotation.length);
            set.addAll(Arrays.asList(parameterAnnotation));
            annotations.add(set);
        }

        final Set<Annotation> mtdAnnotations = new HashSet<>(Arrays.asList(ic.getMethod().getAnnotations()));
        final CacheResult cacheResult = ic.getMethod().getAnnotation(CacheResult.class);
        final String cacheResultCacheResultName = cacheResult == null ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName());
        final CacheResolverFactory cacheResultCacheResolverFactory = cacheResult == null ?
                null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory());
        final CacheKeyGenerator cacheResultCacheKeyGenerator = cacheResult == null ?
                null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator());

        final CachePut cachePut = ic.getMethod().getAnnotation(CachePut.class);
        final String cachePutCachePutName = cachePut == null ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName());
        final CacheResolverFactory cachePutCacheResolverFactory = cachePut == null ?
                null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory());
        final CacheKeyGenerator cachePutCacheKeyGenerator = cachePut == null ?
                null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator());

        final CacheRemove cacheRemove = ic.getMethod().getAnnotation(CacheRemove.class);
        final String cacheRemoveCacheRemoveName = cacheRemove == null ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName());
        final CacheResolverFactory cacheRemoveCacheResolverFactory = cacheRemove == null ?
                null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory());
        final CacheKeyGenerator cacheRemoveCacheKeyGenerator = cacheRemove == null ?
                null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator());

        final CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(CacheRemoveAll.class);
        final String cacheRemoveAllCacheRemoveAllName = cacheRemoveAll == null ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName());
        final CacheResolverFactory cacheRemoveAllCacheResolverFactory = cacheRemoveAll == null ?
                null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory());

        return new MethodMeta(
                parameterTypes,
                annotations,
                mtdAnnotations,
                keyParameterIndexes(ic.getMethod()),
                getValueParameter(annotations),
                getKeyParameters(annotations),
                cacheResultCacheResultName,
                cacheResultCacheResolverFactory,
                cacheResultCacheKeyGenerator,
                cacheResult,
                cachePutCachePutName,
                cachePutCacheResolverFactory,
                cachePutCacheKeyGenerator,
                cachePut != null && cachePut.afterInvocation(),
                cachePut,
                cacheRemoveCacheRemoveName,
                cacheRemoveCacheResolverFactory,
                cacheRemoveCacheKeyGenerator,
                cacheRemove != null && cacheRemove.afterInvocation(),
                cacheRemove,
                cacheRemoveAllCacheRemoveAllName,
                cacheRemoveAllCacheResolverFactory,
                cacheRemoveAll != null && cacheRemoveAll.afterInvocation(),
                cacheRemoveAll);
    }

    private Integer[] getKeyParameters(final List<Set<Annotation>> annotations)
    {
        final Collection<Integer> list = new ArrayList<>();
        int idx = 0;
        for (final Set<Annotation> set : annotations)
        {
            for (final Annotation a : set)
            {
                if (a.annotationType() == CacheKey.class)
                {
                    list.add(idx);
                }
            }
            idx++;
        }
        if (list.isEmpty())
        {
            for (int i = 0; i < annotations.size(); i++)
            {
                list.add(i);
            }
        }
        return list.toArray(new Integer[list.size()]);
    }

    private Integer getValueParameter(final List<Set<Annotation>> annotations)
    {
        final int idx = 0;
        for (final Set<Annotation> set : annotations)
        {
            for (final Annotation a : set)
            {
                if (a.annotationType() == CacheValue.class)
                {
                    return idx;
                }
            }
        }
        return -1;
    }

    private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName)
    {
        if (!cacheName.isEmpty())
        {
            return cacheName;
        }
        if (defaults != null)
        {
            final String name = defaults.cacheName();
            if (!name.isEmpty())
            {
                return name;
            }
        }

        final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName());
        name.append(".");
        name.append(method.getName());
        name.append("(");
        final Class<?>[] parameterTypes = method.getParameterTypes();
        for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++)
        {
            name.append(parameterTypes[pIdx].getName());
            if ((pIdx + 1) < parameterTypes.length)
            {
                name.append(",");
            }
        }
        name.append(")");
        return name.toString();
    }

    private CacheDefaults findDefaults(final Class<?> targetType, final Method method)
    {
        if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations
        {
            final Class<?> api = method.getDeclaringClass();
            for (final Class<?> type : targetType
                                         .getInterfaces())
            {
                if (!api.isAssignableFrom(type))
                {
                    continue;
                }
                return extractDefaults(type);
            }
        }
        return extractDefaults(targetType);
    }

    private CacheDefaults extractDefaults(final Class<?> type)
    {
        CacheDefaults annotation = null;
        Class<?> clazz = type;
        while (clazz != null && clazz != Object.class)
        {
            annotation = clazz.getAnnotation(CacheDefaults.class);
            if (annotation != null)
            {
                break;
            }
            clazz = clazz.getSuperclass();
        }
        return annotation;
    }

    public boolean isIncluded(final Class<?> aClass, final Class<?>[] in, final Class<?>[] out)
    {
        if (in.length == 0 && out.length == 0)
        {
            return false;
        }
        for (final Class<?> potentialIn : in)
        {
            if (potentialIn.isAssignableFrom(aClass))
            {
                for (final Class<?> potentialOut : out)
                {
                    if (potentialOut.isAssignableFrom(aClass))
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, final Class<? extends CacheKeyGenerator> cacheKeyGenerator)
    {
        if (!CacheKeyGenerator.class.equals(cacheKeyGenerator))
        {
            return instance(cacheKeyGenerator);
        }
        if (defaults != null)
        {
            final Class<? extends CacheKeyGenerator> defaultCacheKeyGenerator = defaults.cacheKeyGenerator();
            if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator))
            {
                return instance(defaultCacheKeyGenerator);
            }
        }
        return defaultCacheKeyGenerator;
    }

    private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, final Class<? extends CacheResolverFactory> cacheResolverFactory)
    {
        if (!CacheResolverFactory.class.equals(cacheResolverFactory))
        {
            return instance(cacheResolverFactory);
        }
        if (defaults != null)
        {
            final Class<? extends CacheResolverFactory> defaultCacheResolverFactory = defaults.cacheResolverFactory();
            if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory))
            {
                return instance(defaultCacheResolverFactory);
            }
        }
        return defaultCacheResolverFactory();
    }

    private <T> T instance(final Class<T> type)
    {
        final Set<Bean<?>> beans = beanManager.getBeans(type);
        if (beans.isEmpty())
        {
            if (CacheKeyGenerator.class == type) {
                return (T) defaultCacheKeyGenerator;
            }
            if (CacheResolverFactory.class == type) {
                return (T) defaultCacheResolverFactory();
            }
            return null;
        }
        final Bean<?> bean = beanManager.resolve(beans);
        final CreationalContext<?> context = beanManager.createCreationalContext(bean);
        final Class<? extends Annotation> scope = bean.getScope();
        final boolean normalScope = beanManager.isNormalScope(scope);
        try
        {
            final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context);
            if (!normalScope)
            {
                toRelease.add(context);
            }
            return (T) reference;
        }
        finally
        {
            if (normalScope)
            { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe?
                context.release();
            }
        }
    }

    private CacheResolverFactoryImpl defaultCacheResolverFactory()
    {
        if (defaultCacheResolverFactory != null) {
            return defaultCacheResolverFactory;
        }
        synchronized (this) {
            if (defaultCacheResolverFactory != null) {
                return defaultCacheResolverFactory;
            }
            defaultCacheResolverFactory = new CacheResolverFactoryImpl();
        }
        return defaultCacheResolverFactory;
    }

    private Integer[] keyParameterIndexes(final Method method)
    {
        final List<Integer> keys = new LinkedList<>();
        final Annotation[][] parameterAnnotations = method.getParameterAnnotations();

        // first check if keys are specified explicitely
        for (int i = 0; i < method.getParameterTypes().length; i++)
        {
            final Annotation[] annotations = parameterAnnotations[i];
            for (final Annotation a : annotations)
            {
                if (a.annotationType().equals(CacheKey.class))
                {
                    keys.add(i);
                    break;
                }
            }
        }

        // if not then use all parameters but value ones
        if (keys.isEmpty())
        {
            for (int i = 0; i < method.getParameterTypes().length; i++)
            {
                final Annotation[] annotations = parameterAnnotations[i];
                boolean value = false;
                for (final Annotation a : annotations)
                {
                    if (a.annotationType().equals(CacheValue.class))
                    {
                        value = true;
                        break;
                    }
                }
                if (!value) {
                    keys.add(i);
                }
            }
        }
        return keys.toArray(new Integer[keys.size()]);
    }

    private static final class MethodKey
    {
        private final Class<?> base;
        private final Method delegate;
        private final int hash;

        private MethodKey(final Class<?> base, final Method delegate)
        {
            this.base = base; // we need a class to ensure inheritance don't fall in the same key
            this.delegate = delegate;
            this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode());
        }

        @Override
        public boolean equals(final Object o)
        {
            if (this == o)
            {
                return true;
            }
            if (o == null || getClass() != o.getClass())
            {
                return false;
            }
            final MethodKey classKey = MethodKey.class.cast(o);
            return delegate.equals(classKey.delegate) && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base)));
        }

        @Override
        public int hashCode()
        {
            return hash;
        }
    }

    // TODO: split it in 5?
    public static class MethodMeta
    {
        private final Class<?>[] parameterTypes;
        private final List<Set<Annotation>> parameterAnnotations;
        private final Set<Annotation> annotations;
        private final Integer[] keysIndices;
        private final Integer valueIndex;
        private final Integer[] parameterIndices;

        private final String cacheResultCacheName;
        private final CacheResolverFactory cacheResultResolverFactory;
        private final CacheKeyGenerator cacheResultKeyGenerator;
        private final CacheResult cacheResult;

        private final String cachePutCacheName;
        private final CacheResolverFactory cachePutResolverFactory;
        private final CacheKeyGenerator cachePutKeyGenerator;
        private final boolean cachePutAfter;
        private final CachePut cachePut;

        private final String cacheRemoveCacheName;
        private final CacheResolverFactory cacheRemoveResolverFactory;
        private final CacheKeyGenerator cacheRemoveKeyGenerator;
        private final boolean cacheRemoveAfter;
        private final CacheRemove cacheRemove;

        private final String cacheRemoveAllCacheName;
        private final CacheResolverFactory cacheRemoveAllResolverFactory;
        private final boolean cacheRemoveAllAfter;
        private final CacheRemoveAll cacheRemoveAll;

        public MethodMeta(final Class<?>[] parameterTypes, final List<Set<Annotation>> parameterAnnotations, final Set<Annotation>
                annotations, final Integer[] keysIndices, final Integer valueIndex, final Integer[] parameterIndices, final String
                cacheResultCacheName, final CacheResolverFactory cacheResultResolverFactory, final CacheKeyGenerator
                cacheResultKeyGenerator, final CacheResult cacheResult, final String cachePutCacheName, final CacheResolverFactory
                cachePutResolverFactory, final CacheKeyGenerator cachePutKeyGenerator, final boolean cachePutAfter, final CachePut cachePut, final String
                cacheRemoveCacheName, final CacheResolverFactory cacheRemoveResolverFactory, final CacheKeyGenerator
                cacheRemoveKeyGenerator, final boolean cacheRemoveAfter, final CacheRemove cacheRemove, final String cacheRemoveAllCacheName,
                          final CacheResolverFactory cacheRemoveAllResolverFactory, final boolean
                                  cacheRemoveAllAfter, final CacheRemoveAll cacheRemoveAll)
        {
            this.parameterTypes = parameterTypes;
            this.parameterAnnotations = parameterAnnotations;
            this.annotations = annotations;
            this.keysIndices = keysIndices;
            this.valueIndex = valueIndex;
            this.parameterIndices = parameterIndices;
            this.cacheResultCacheName = cacheResultCacheName;
            this.cacheResultResolverFactory = cacheResultResolverFactory;
            this.cacheResultKeyGenerator = cacheResultKeyGenerator;
            this.cacheResult = cacheResult;
            this.cachePutCacheName = cachePutCacheName;
            this.cachePutResolverFactory = cachePutResolverFactory;
            this.cachePutKeyGenerator = cachePutKeyGenerator;
            this.cachePutAfter = cachePutAfter;
            this.cachePut = cachePut;
            this.cacheRemoveCacheName = cacheRemoveCacheName;
            this.cacheRemoveResolverFactory = cacheRemoveResolverFactory;
            this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator;
            this.cacheRemoveAfter = cacheRemoveAfter;
            this.cacheRemove = cacheRemove;
            this.cacheRemoveAllCacheName = cacheRemoveAllCacheName;
            this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory;
            this.cacheRemoveAllAfter = cacheRemoveAllAfter;
            this.cacheRemoveAll = cacheRemoveAll;
        }

        public boolean isCacheRemoveAfter()
        {
            return cacheRemoveAfter;
        }

        public boolean isCachePutAfter()
        {
            return cachePutAfter;
        }

        public Class<?>[] getParameterTypes()
        {
            return parameterTypes;
        }

        public List<Set<Annotation>> getParameterAnnotations()
        {
            return parameterAnnotations;
        }

        public String getCacheResultCacheName()
        {
            return cacheResultCacheName;
        }

        public CacheResolverFactory getCacheResultResolverFactory()
        {
            return cacheResultResolverFactory;
        }

        public CacheKeyGenerator getCacheResultKeyGenerator()
        {
            return cacheResultKeyGenerator;
        }

        public CacheResult getCacheResult() {
            return cacheResult;
        }

        public Integer[] getParameterIndices()
        {
            return parameterIndices;
        }

        public Set<Annotation> getAnnotations()
        {
            return annotations;
        }

        public Integer[] getKeysIndices()
        {
            return keysIndices;
        }

        public Integer getValuesIndex()
        {
            return valueIndex;
        }

        public Integer getValueIndex()
        {
            return valueIndex;
        }

        public String getCachePutCacheName()
        {
            return cachePutCacheName;
        }

        public CacheResolverFactory getCachePutResolverFactory()
        {
            return cachePutResolverFactory;
        }

        public CacheKeyGenerator getCachePutKeyGenerator()
        {
            return cachePutKeyGenerator;
        }

        public CachePut getCachePut()
        {
            return cachePut;
        }

        public String getCacheRemoveCacheName()
        {
            return cacheRemoveCacheName;
        }

        public CacheResolverFactory getCacheRemoveResolverFactory()
        {
            return cacheRemoveResolverFactory;
        }

        public CacheKeyGenerator getCacheRemoveKeyGenerator()
        {
            return cacheRemoveKeyGenerator;
        }

        public CacheRemove getCacheRemove()
        {
            return cacheRemove;
        }

        public String getCacheRemoveAllCacheName()
        {
            return cacheRemoveAllCacheName;
        }

        public CacheResolverFactory getCacheRemoveAllResolverFactory()
        {
            return cacheRemoveAllResolverFactory;
        }

        public boolean isCacheRemoveAllAfter()
        {
            return cacheRemoveAllAfter;
        }

        public CacheRemoveAll getCacheRemoveAll()
        {
            return cacheRemoveAll;
        }
    }
}
