/*
 * 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.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;
import freemarker.template.utility.NullArgumentException;

final class ClassIntrospectorBuilder implements Cloneable {

    private static final Map<ClassIntrospectorBuilder, Reference<ClassIntrospector>> INSTANCE_CACHE
            = new HashMap<ClassIntrospectorBuilder, Reference<ClassIntrospector>>();
    private static final ReferenceQueue<ClassIntrospector> INSTANCE_CACHE_REF_QUEUE
            = new ReferenceQueue<ClassIntrospector>();

    private final Version incompatibleImprovements;

    // Properties and their *defaults*:
    private int exposureLevel = BeansWrapper.EXPOSE_SAFE;
    private boolean exposeFields;
    private MemberAccessPolicy memberAccessPolicy;
    private boolean treatDefaultMethodsAsBeanMembers;
    private MethodAppearanceFineTuner methodAppearanceFineTuner;
    private MethodSorter methodSorter;
    // Attention:
    // - This is also used as a cache key, so non-normalized field values should be avoided.
    // - If some field has a default value, it must be set until the end of the constructor. No field that has a
    //   default can be left unset (like null).
    // - If you add a new field, review all methods in this class, also the ClassIntrospector constructor
    
    ClassIntrospectorBuilder(ClassIntrospector ci) {
        incompatibleImprovements = ci.incompatibleImprovements;
        exposureLevel = ci.exposureLevel;
        exposeFields = ci.exposeFields;
        memberAccessPolicy = ci.memberAccessPolicy;
        treatDefaultMethodsAsBeanMembers = ci.treatDefaultMethodsAsBeanMembers;
        methodAppearanceFineTuner = ci.methodAppearanceFineTuner;
        methodSorter = ci.methodSorter;
    }
    
    ClassIntrospectorBuilder(Version incompatibleImprovements) {
        // Warning: incompatibleImprovements must not affect this object at versions increments where there's no
        // change in the BeansWrapper.normalizeIncompatibleImprovements results. That is, this class may don't react
        // to some version changes that affects BeansWrapper, but not the other way around.
        this.incompatibleImprovements = normalizeIncompatibleImprovementsVersion(incompatibleImprovements);
        treatDefaultMethodsAsBeanMembers
                = incompatibleImprovements.intValue() >= _TemplateAPI.VERSION_INT_2_3_26;
        memberAccessPolicy = DefaultMemberAccessPolicy.getInstance(this.incompatibleImprovements);
    }

    private static Version normalizeIncompatibleImprovementsVersion(Version incompatibleImprovements) {
        _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
        // All breakpoints here must occur in BeansWrapper.normalizeIncompatibleImprovements!
        return incompatibleImprovements.intValue() >= _TemplateAPI.VERSION_INT_2_3_30 ? Configuration.VERSION_2_3_30
                : incompatibleImprovements.intValue() >= _TemplateAPI.VERSION_INT_2_3_21 ? Configuration.VERSION_2_3_21
                : Configuration.VERSION_2_3_0;
    }

    @Override
    protected Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("Failed to clone ClassIntrospectorBuilder", e);
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + incompatibleImprovements.hashCode();
        result = prime * result + (exposeFields ? 1231 : 1237);
        result = prime * result + (treatDefaultMethodsAsBeanMembers ? 1231 : 1237);
        result = prime * result + exposureLevel;
        result = prime * result + memberAccessPolicy.hashCode();
        result = prime * result + System.identityHashCode(methodAppearanceFineTuner);
        result = prime * result + System.identityHashCode(methodSorter);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        ClassIntrospectorBuilder other = (ClassIntrospectorBuilder) obj;
        
        if (!incompatibleImprovements.equals(other.incompatibleImprovements)) return false;
        if (exposeFields != other.exposeFields) return false;
        if (treatDefaultMethodsAsBeanMembers != other.treatDefaultMethodsAsBeanMembers) return false;
        if (exposureLevel != other.exposureLevel) return false;
        if (!memberAccessPolicy.equals(other.memberAccessPolicy)) return false;
        if (methodAppearanceFineTuner != other.methodAppearanceFineTuner) return false;
        if (methodSorter != other.methodSorter) return false;
        
        return true;
    }
    
    public int getExposureLevel() {
        return exposureLevel;
    }

    /** See {@link BeansWrapper#setExposureLevel(int)}. */
    public void setExposureLevel(int exposureLevel) {
        if (exposureLevel < BeansWrapper.EXPOSE_ALL || exposureLevel > BeansWrapper.EXPOSE_NOTHING) {
            throw new IllegalArgumentException("Illegal exposure level: " + exposureLevel);
        }
        
        this.exposureLevel = exposureLevel;
    }

    public boolean getExposeFields() {
        return exposeFields;
    }

    /** See {@link BeansWrapper#setExposeFields(boolean)}. */
    public void setExposeFields(boolean exposeFields) {
        this.exposeFields = exposeFields;
    }
    
    public boolean getTreatDefaultMethodsAsBeanMembers() {
        return treatDefaultMethodsAsBeanMembers;
    }

    public void setTreatDefaultMethodsAsBeanMembers(boolean treatDefaultMethodsAsBeanMembers) {
        this.treatDefaultMethodsAsBeanMembers = treatDefaultMethodsAsBeanMembers;
    }

    public MemberAccessPolicy getMemberAccessPolicy() {
        return memberAccessPolicy;
    }

    public void setMemberAccessPolicy(MemberAccessPolicy memberAccessPolicy) {
        NullArgumentException.check(memberAccessPolicy);
        this.memberAccessPolicy = memberAccessPolicy;
    }

    public MethodAppearanceFineTuner getMethodAppearanceFineTuner() {
        return methodAppearanceFineTuner;
    }

    public void setMethodAppearanceFineTuner(MethodAppearanceFineTuner methodAppearanceFineTuner) {
        this.methodAppearanceFineTuner = methodAppearanceFineTuner;
    }

    public MethodSorter getMethodSorter() {
        return methodSorter;
    }

    public void setMethodSorter(MethodSorter methodSorter) {
        this.methodSorter = methodSorter;
    }

    /**
     * Returns the normalized incompatible improvements.
     */
    public Version getIncompatibleImprovements() {
        return incompatibleImprovements;
    }

    private static void removeClearedReferencesFromInstanceCache() {
        Reference<? extends ClassIntrospector> clearedRef;
        while ((clearedRef = INSTANCE_CACHE_REF_QUEUE.poll()) != null) {
            synchronized (INSTANCE_CACHE) {
                findClearedRef: for (Iterator<Reference<ClassIntrospector>> it = INSTANCE_CACHE.values().iterator();
                         it.hasNext(); ) {
                    if (it.next() == clearedRef) {
                        it.remove();
                        break findClearedRef;
                    }
                }
            }
        }
    }

    /** For unit testing only */
    static void clearInstanceCache() {
        synchronized (INSTANCE_CACHE) {
            INSTANCE_CACHE.clear();
        }
    }
    
    /** For unit testing only */
    static Map<ClassIntrospectorBuilder, Reference<ClassIntrospector>> getInstanceCache() {
        return INSTANCE_CACHE;
    }

    /**
     * Returns an instance that is possibly shared (singleton). Note that this comes with its own "shared lock",
     * since everyone who uses this object will have to lock with that common object.
     */
    ClassIntrospector build() {
        if ((methodAppearanceFineTuner == null || methodAppearanceFineTuner instanceof SingletonCustomizer)
                && (methodSorter == null || methodSorter instanceof SingletonCustomizer)) {
            // Instance can be cached.
            ClassIntrospector instance;
            synchronized (INSTANCE_CACHE) {
                Reference<ClassIntrospector> instanceRef = INSTANCE_CACHE.get(this);
                instance = instanceRef != null ? instanceRef.get() : null;
                if (instance == null) {
                    ClassIntrospectorBuilder thisClone = (ClassIntrospectorBuilder) clone();  // prevent any aliasing issues
                    instance = new ClassIntrospector(thisClone, new Object(), true, true);
                    INSTANCE_CACHE.put(thisClone, new WeakReference<ClassIntrospector>(instance, INSTANCE_CACHE_REF_QUEUE));
                }
            }
            
            removeClearedReferencesFromInstanceCache();
            
            return instance;
        } else {
            // If methodAppearanceFineTuner or methodSorter is specified and isn't marked as a singleton, the
            // ClassIntrospector can't be shared/cached as those objects could contain a back-reference to the
            // BeansWrapper.
            return new ClassIntrospector(this, new Object(), true, false);
        }
    }

}