/**
 * 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.cxf.jaxrs.model;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.ReflectionUtil;
import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
import org.apache.cxf.jaxrs.utils.InjectionUtils;

public abstract class AbstractResourceInfo {
    public static final String CONSTRUCTOR_PROXY_MAP = "jaxrs-constructor-proxy-map";
    private static final Logger LOG = LogUtils.getL7dLogger(AbstractResourceInfo.class);
    private static final String FIELD_PROXY_MAP = "jaxrs-field-proxy-map";
    private static final String SETTER_PROXY_MAP = "jaxrs-setter-proxy-map";

    protected boolean root;
    protected Class<?> resourceClass;
    protected Class<?> serviceClass;

    private Map<Class<?>, List<Field>> contextFields;
    private Map<Class<?>, Map<Class<?>, Method>> contextMethods;
    private Bus bus;
    private boolean constructorProxiesAvailable;
    private boolean contextsAvailable;

    protected AbstractResourceInfo(Bus bus) {
        this.bus = bus;
    }

    protected AbstractResourceInfo(Class<?> resourceClass, Class<?> serviceClass,
                                   boolean isRoot, boolean checkContexts, Bus bus) {
        this(resourceClass, serviceClass, isRoot, checkContexts, null, bus, null);
    }

    protected AbstractResourceInfo(Class<?> resourceClass,
                                   Class<?> serviceClass,
                                   boolean isRoot,
                                   boolean checkContexts,
                                   Map<Class<?>, ThreadLocalProxy<?>> constructorProxies,
                                   Bus bus,
                                   Object provider) {
        this.bus = bus;
        this.serviceClass = serviceClass;
        this.resourceClass = resourceClass;
        root = isRoot;
        if (checkContexts && resourceClass != null) {
            findContexts(serviceClass, provider, constructorProxies);
        }
    }

    private void findContexts(Class<?> cls, Object provider,
                              Map<Class<?>, ThreadLocalProxy<?>> constructorProxies) {
        findContextFields(cls, provider);
        findContextSetterMethods(cls, provider);
        if (constructorProxies != null) {
            Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> proxies = getConstructorProxyMap();
            proxies.put(serviceClass, constructorProxies);
            constructorProxiesAvailable = true;
        }


        contextsAvailable = contextFields != null && !contextFields.isEmpty()
            || contextMethods != null && !contextMethods.isEmpty()
            || constructorProxiesAvailable;
    }

    public boolean contextsAvailable() {
        return contextsAvailable;
    }

    public Bus getBus() {
        return bus;
    }

    public void setResourceClass(Class<?> rClass) {
        resourceClass = rClass;
        if (serviceClass.isInterface() && resourceClass != null && !resourceClass.isInterface()) {
            findContexts(resourceClass, null, null);
        }
    }

    public Class<?> getServiceClass() {
        return serviceClass;
    }

    private void findContextFields(Class<?> cls, Object provider) {
        if (cls == Object.class || cls == null) {
            return;
        }
        for (Field f : ReflectionUtil.getDeclaredFields(cls)) {
            for (Annotation a : f.getAnnotations()) {
                if (a.annotationType() == Context.class
                    && (f.getType().isInterface() || f.getType() == Application.class)) {
                    contextFields = addContextField(contextFields, f);
                    checkContextClass(f.getType());
                    if (!InjectionUtils.VALUE_CONTEXTS.contains(f.getType().getName())) {
                        addToMap(getFieldProxyMap(true), f, getFieldThreadLocalProxy(f, provider));
                    }
                }
            }
        }
        findContextFields(cls.getSuperclass(), provider);
    }

    private static ThreadLocalProxy<?> getFieldThreadLocalProxy(Field f, Object provider) {
        if (provider != null) {
            Object proxy = null;
            synchronized (provider) {
                try {
                    proxy = InjectionUtils.extractFieldValue(f, provider);
                } catch (Throwable t) {
                    // continue
                }
                if (!(proxy instanceof ThreadLocalProxy)) {
                    proxy = InjectionUtils.createThreadLocalProxy(f.getType());
                    InjectionUtils.injectFieldValue(f, provider, proxy);
                }
            }
            return (ThreadLocalProxy<?>)proxy;
        }
        return InjectionUtils.createThreadLocalProxy(f.getType());
    }

    private static ThreadLocalProxy<?> getMethodThreadLocalProxy(Method m, Object provider) {
        if (provider != null) {
            Object proxy = null;
            synchronized (provider) {
                try {
                    proxy = InjectionUtils.extractFromMethod(provider,
                                                             InjectionUtils.getGetterFromSetter(m),
                                                             false);
                } catch (Throwable t) {
                    // continue
                }
                if (!(proxy instanceof ThreadLocalProxy)) {
                    proxy = InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]);
                    InjectionUtils.injectThroughMethod(provider, m, proxy);
                }
            }
            return (ThreadLocalProxy<?>)proxy;
        }
        return InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]);
    }

    @SuppressWarnings("unchecked")
    private <T> Map<Class<?>, Map<T, ThreadLocalProxy<?>>> getProxyMap(String prop, boolean create) {
        // Avoid synchronizing on the bus for a ConcurrentHashMAp
        if (bus.getProperties() instanceof ConcurrentHashMap) {
            return (Map<Class<?>, Map<T, ThreadLocalProxy<?>>>) bus.getProperties().computeIfAbsent(prop, k ->
                new ConcurrentHashMap<Class<?>, Map<T, ThreadLocalProxy<?>>>(2)
            );
        }

        Object property;
        synchronized (bus) {
            property = bus.getProperty(prop);
            if (property == null && create) {
                Map<Class<?>, Map<T, ThreadLocalProxy<?>>> map
                    = new ConcurrentHashMap<>(2);
                bus.setProperty(prop, map);
                property = map;
            }
        }
        return (Map<Class<?>, Map<T, ThreadLocalProxy<?>>>)property;
    }

    public Map<Class<?>, ThreadLocalProxy<?>> getConstructorProxies() {
        if (constructorProxiesAvailable) {
            return getConstructorProxyMap().get(serviceClass);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> getConstructorProxyMap() {
        Object property = bus.getProperty(CONSTRUCTOR_PROXY_MAP);
        if (property == null) {
            Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> map
                = new ConcurrentHashMap<>(2);
            bus.setProperty(CONSTRUCTOR_PROXY_MAP, map);
            property = map;
        }
        return (Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>>)property;
    }

    private Map<Class<?>, Map<Field, ThreadLocalProxy<?>>> getFieldProxyMap(boolean create) {
        return getProxyMap(FIELD_PROXY_MAP, create);
    }

    private Map<Class<?>, Map<Method, ThreadLocalProxy<?>>> getSetterProxyMap(boolean create) {
        return getProxyMap(SETTER_PROXY_MAP, create);
    }

    private void findContextSetterMethods(Class<?> cls, Object provider) {

        for (Method m : cls.getMethods()) {

            if (!m.getName().startsWith("set") || m.getParameterTypes().length != 1) {
                continue;
            }
            for (Annotation a : m.getAnnotations()) {
                if (a.annotationType() == Context.class) {
                    checkContextMethod(m, provider);
                    break;
                }
            }
        }
        Class<?>[] interfaces = cls.getInterfaces();
        for (Class<?> i : interfaces) {
            findContextSetterMethods(i, provider);
        }
        Class<?> superCls = cls.getSuperclass();
        if (superCls != null && superCls != Object.class) {
            findContextSetterMethods(superCls, provider);
        }
    }

    private void checkContextMethod(Method m, Object provider) {
        Class<?> type = m.getParameterTypes()[0];
        if (type.isInterface() || type == Application.class) {
            checkContextClass(type);
            addContextMethod(type, m, provider);
        }
    }
    private void checkContextClass(Class<?> type) {
        if (!InjectionUtils.STANDARD_CONTEXT_CLASSES.contains(type.getName())) {
            LOG.fine("Injecting a custom context " + type.getName()
                     + ", ContextProvider is required for this type");
        }
    }

    public Map<Class<?>, Method> getContextMethods() {
        Map<Class<?>, Method> methods = contextMethods == null ? null : contextMethods.get(getServiceClass());
        return methods == null ? Collections.emptyMap()
                                      : Collections.unmodifiableMap(methods);
    }

    private void addContextMethod(Class<?> contextClass, Method m, Object provider) {
        if (contextMethods == null) {
            contextMethods = new HashMap<>();
        }
        addToMap(contextMethods, contextClass, m);
        if (!InjectionUtils.VALUE_CONTEXTS.contains(m.getParameterTypes()[0].getName())) {
            addToMap(getSetterProxyMap(true), m, getMethodThreadLocalProxy(m, provider));
        }
    }

    public boolean isRoot() {
        return root;
    }

    public Class<?> getResourceClass() {
        return resourceClass;
    }

    public List<Field> getContextFields() {
        return getList(contextFields);
    }

    public ThreadLocalProxy<?> getContextFieldProxy(Field f) {
        return getProxy(getFieldProxyMap(true), f);
    }

    public ThreadLocalProxy<?> getContextSetterProxy(Method m) {
        return getProxy(getSetterProxyMap(true), m);
    }

    public abstract boolean isSingleton();

    @SuppressWarnings("rawtypes")
    public static void clearAllMaps() {
        Bus bus = BusFactory.getThreadDefaultBus(false);
        if (bus != null) {
            Object property = bus.getProperty(FIELD_PROXY_MAP);
            if (property != null) {
                ((Map)property).clear();
            }
            property = bus.getProperty(SETTER_PROXY_MAP);
            if (property != null) {
                ((Map)property).clear();
            }
            property = bus.getProperty(CONSTRUCTOR_PROXY_MAP);
            if (property != null) {
                ((Map)property).clear();
            }
        }
    }

    public void clearThreadLocalProxies() {
        clearProxies(getFieldProxyMap(false));
        clearProxies(getSetterProxyMap(false));
        clearProxies(getConstructorProxyMap());
    }

    private <T> void clearProxies(Map<Class<?>, Map<T, ThreadLocalProxy<?>>> tlps) {
        Map<T, ThreadLocalProxy<?>> proxies = tlps == null ? null : tlps.get(getServiceClass());
        if (proxies == null) {
            return;
        }
        for (ThreadLocalProxy<?> tlp : proxies.values()) {
            if (tlp != null) {
                tlp.remove();
            }
        }
    }

    private Map<Class<?>, List<Field>> addContextField(Map<Class<?>, List<Field>> theFields, Field f) {
        if (theFields == null) {
            theFields = new HashMap<>();
        }

        List<Field> fields = theFields.get(serviceClass);
        if (fields == null) {
            fields = new ArrayList<>();
            theFields.put(serviceClass, fields);
        }
        if (!fields.contains(f)) {
            fields.add(f);
        }
        return theFields;
    }

    private <T, V> void addToMap(Map<Class<?>, Map<T, V>> proxyMap,
                                 T f,
                                 V proxy) {
        Map<T, V> proxies = proxyMap.get(serviceClass);
        if (proxies == null) {
            proxies = new ConcurrentHashMap<>();
            proxyMap.put(serviceClass, proxies);
        }
        if (!proxies.containsKey(f)) {
            proxies.put(f, proxy);
        }
    }

    private List<Field> getList(Map<Class<?>, List<Field>> fields) {
        List<Field> ret = fields == null ? null : fields.get(getServiceClass());
        if (ret != null) {
            ret = Collections.unmodifiableList(ret);
        } else {
            ret = Collections.emptyList();
        }
        return ret;
    }

    private <T> ThreadLocalProxy<?> getProxy(Map<Class<?>, Map<T, ThreadLocalProxy<?>>> proxies,
                                             T key) {

        Map<?, ThreadLocalProxy<?>> theMap = proxies == null ? null : proxies.get(getServiceClass());
        ThreadLocalProxy<?> ret = null;
        if (theMap != null) {
            ret = theMap.get(key);
        }
        return ret;
    }
}
