/*
 * 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 freemarker.ext.beans;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import freemarker.core.BugException;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.CollectionUtils;

/**
 * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
 * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
 * access things inside this package that users shouldn't. 
 */ 
public class _BeansAPI {

    private _BeansAPI() { }
    
    public static String getAsClassicCompatibleString(BeanModel bm) {
        return bm.getAsClassicCompatibleString();
    }
    
    public static Object newInstance(Class<?> pClass, Object[] args, BeansWrapper bw)
            throws NoSuchMethodException, IllegalArgumentException, InstantiationException,
            IllegalAccessException, InvocationTargetException, TemplateModelException {
        return newInstance(getConstructorDescriptor(pClass, args), args, bw);
    }
    
    /**
     * Gets the constructor that matches the types of the arguments the best. So this is more
     * than what the Java reflection API provides in that it can handle overloaded constructors. This re-uses the
     * overloaded method selection logic of {@link BeansWrapper}.
     */
    private static CallableMemberDescriptor getConstructorDescriptor(Class<?> pClass, Object[] args)
            throws NoSuchMethodException {
        if (args == null) args = CollectionUtils.EMPTY_OBJECT_ARRAY;
        
        final ArgumentTypes argTypes = new ArgumentTypes(args, true);
        final List<ReflectionCallableMemberDescriptor> fixedArgMemberDescs
                = new ArrayList<>();
        final List<ReflectionCallableMemberDescriptor> varArgsMemberDescs
                = new ArrayList<>();
        final Constructor<?>[] constrs = pClass.getConstructors();
        for (int i = 0; i < constrs.length; i++) {
            Constructor<?> constr = constrs[i];
            ReflectionCallableMemberDescriptor memberDesc = new ReflectionCallableMemberDescriptor(constr, constr.getParameterTypes());
            if (!_MethodUtil.isVarargs(constr)) {
                fixedArgMemberDescs.add(memberDesc);
            } else {
                varArgsMemberDescs.add(memberDesc);
            }
        }
        
        MaybeEmptyCallableMemberDescriptor contrDesc = argTypes.getMostSpecific(fixedArgMemberDescs, false);
        if (contrDesc == EmptyCallableMemberDescriptor.NO_SUCH_METHOD) {
            contrDesc = argTypes.getMostSpecific(varArgsMemberDescs, true);
        }
        
        if (contrDesc instanceof EmptyCallableMemberDescriptor) {
            if (contrDesc == EmptyCallableMemberDescriptor.NO_SUCH_METHOD) {
                throw new NoSuchMethodException(
                        "There's no public " + pClass.getName()
                        + " constructor with compatible parameter list.");
            } else if (contrDesc == EmptyCallableMemberDescriptor.AMBIGUOUS_METHOD) {
                throw new NoSuchMethodException(
                        "There are multiple public " + pClass.getName()
                        + " constructors that match the compatible parameter list with the same preferability.");
            } else {
                throw new NoSuchMethodException();
            }
        } else {
            return (CallableMemberDescriptor) contrDesc;
        }
    }
    
    private static Object newInstance(CallableMemberDescriptor constrDesc, Object[] args, BeansWrapper bw)
            throws InstantiationException, IllegalAccessException, InvocationTargetException, IllegalArgumentException,
            TemplateModelException {
        if (args == null) args = CollectionUtils.EMPTY_OBJECT_ARRAY;
        
        final Object[] packedArgs;
        if (constrDesc.isVarargs()) {
            // We have to put all the varargs arguments into a single array argument.

            final Class<?>[] paramTypes = constrDesc.getParamTypes();
            final int fixedArgCnt = paramTypes.length - 1;
            
            packedArgs = new Object[fixedArgCnt + 1]; 
            for (int i = 0; i < fixedArgCnt; i++) {
packedArgs[i] = args[i];
            }
            
            final Class<?> compType = paramTypes[fixedArgCnt].getComponentType();
            final int varArgCnt = args.length - fixedArgCnt;
            final Object varArgsArray = Array.newInstance(compType, varArgCnt);
            for (int i = 0; i < varArgCnt; i++) {
                Array.set(varArgsArray, i, args[fixedArgCnt + i]);
            }
            packedArgs[fixedArgCnt] = varArgsArray;
        } else {
            packedArgs = args;
        }
        
        return constrDesc.invokeConstructor(bw, packedArgs);
    }
    
    /**
     * Contains the common parts of the singleton management for {@link BeansWrapper} and {@link DefaultObjectWrapper}.  
     *  
     * @param beansWrapperSubclassFactory Creates a <em>new</em> read-only object wrapper of the desired
     *     {@link BeansWrapper} subclass. 
     */
    public static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> BW getBeansWrapperSubclassSingleton(
            BWC settings,
            Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
            ReferenceQueue<BW> instanceCacheRefQue,
            _BeansWrapperSubclassFactory<BW, BWC> beansWrapperSubclassFactory) {
        // BeansWrapper can't be cached across different Thread Context Class Loaders (TCCL), because the result of
        // a class name (String) to Class mappings depends on it, and the staticModels and enumModels need that.
        // (The ClassIntrospector doesn't have to consider the TCCL, as it only works with Class-es, not class
        // names.)
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        
        Reference<BW> instanceRef;
        Map<BWC, WeakReference<BW>> tcclScopedCache;
        synchronized (instanceCache) {
            tcclScopedCache = instanceCache.get(tccl);
            if (tcclScopedCache == null) {
                tcclScopedCache = new HashMap<>();
                instanceCache.put(tccl, tcclScopedCache);
                instanceRef = null;
            } else {
                instanceRef = tcclScopedCache.get(settings);
            }
        }

        BW instance = instanceRef != null ? instanceRef.get() : null;
        if (instance != null) {  // cache hit
            return instance;
        }
        // cache miss
        
        settings = clone(settings);  // prevent any aliasing issues 
        instance = beansWrapperSubclassFactory.create(settings);
        if (!instance.isWriteProtected()) {
            throw new BugException();
        }
        
        synchronized (instanceCache) {
            instanceRef = tcclScopedCache.get(settings);
            BW concurrentInstance = instanceRef != null ? instanceRef.get() : null;
            if (concurrentInstance == null) {
                tcclScopedCache.put(settings, new WeakReference<>(instance, instanceCacheRefQue));
            } else {
                instance = concurrentInstance;
            }
        }
        
        removeClearedReferencesFromCache(instanceCache, instanceCacheRefQue);
        
        return instance;
    }

    @SuppressWarnings("unchecked")
    private static <BWC extends BeansWrapperConfiguration> BWC clone(BWC settings) {
        return (BWC) settings.clone(true);
    }
    
    private static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration>
            void removeClearedReferencesFromCache(
                    Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
                    ReferenceQueue<BW> instanceCacheRefQue) {
        Reference<? extends BW> clearedRef;
        while ((clearedRef = instanceCacheRefQue.poll()) != null) {
            synchronized (instanceCache) {
                findClearedRef: for (Map<BWC, WeakReference<BW>> tcclScopedCache : instanceCache.values()) {
                    for (Iterator<WeakReference<BW>> it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
                        if (it2.next() == clearedRef) {
                            it2.remove();
                            break findClearedRef;
                        }
                    }
                }
            } // sync
        } // while poll
    }
    
    /**
     * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
     */
    public interface _BeansWrapperSubclassFactory<BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> {
        
        /** Creates a new read-only {@link BeansWrapper}; used for {@link BeansWrapperBuilder} and such. */
        BW create(BWC sa);
    }
    
    public static ClassIntrospectorBuilder getClassIntrospectorBuilder(BeansWrapperConfiguration bwc) {
        return bwc.getClassIntrospectorBuilder();
    }

}
