/*
 * 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.tamaya.spisupport;

import org.apache.tamaya.ConfigException;
import org.apache.tamaya.TypeLiteral;
import org.apache.tamaya.spi.ConversionContext;
import org.apache.tamaya.spi.PropertyConverter;
import org.apache.tamaya.spi.ServiceContext;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Manager that deals with {@link org.apache.tamaya.spi.PropertyConverter} instances.
 * This class is thread-safe.
 */
public class PropertyConverterManager {
    /**
     * The logger used.
     */
    private static final Logger LOG = Logger.getLogger(PropertyConverterManager.class.getName());
    /**
     * The registered converters.
     */
    private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>();
    /**
     * The transitive converters.
     */
    private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> transitiveConverters = new ConcurrentHashMap<>();
    /**
     * The lock used.
     */
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    private static final Comparator<Object> PRIORITY_COMPARATOR = new Comparator<Object>() {

        @Override
        public int compare(Object o1, Object o2) {
            int prio = PriorityServiceComparator.getPriority(o1) - PriorityServiceComparator.getPriority(o2);
            if (prio < 0) {
                return 1;
            } else if (prio > 0) {
                return -1;
            } else {
                return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
            }
        }
    };

    private final ServiceContext serviceContext;

    /**
     * Creates a new instance.
     * @param serviceContext the Service context, not null.
     */
    public PropertyConverterManager(ServiceContext serviceContext) {
        this(serviceContext, false);
    }

    /**
     * Creates a new instance.
     * @param serviceContext the Service context, not null.
     * @param init if true, the converters are loaded eagerly.
     */
    public PropertyConverterManager(ServiceContext serviceContext, boolean init) {
        this.serviceContext = Objects.requireNonNull(serviceContext);
        if (init) {
            initConverters();
        }
    }

    /**
     * Registers the default converters provided out of the box.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void initConverters() {
        for (PropertyConverter conv : serviceContext.getServices(PropertyConverter.class)) {
            Type type = TypeLiteral.getGenericInterfaceTypeParameters(conv.getClass(), PropertyConverter.class)[0];
            register(TypeLiteral.of(type), conv);
        }
    }


    /**
     * Registers a new converters instance.
     *
     * @param targetType the target type, not {@code null}.
     * @param converter  the converters, not {@code null}.
     * @param <T>        the type.
     */
    @SuppressWarnings("unchecked")
    public <T> void register(TypeLiteral<T> targetType, PropertyConverter<T> converter) {
        Objects.requireNonNull(converter);
        Lock writeLock = lock.writeLock();
        try {
            writeLock.lock();
            List<PropertyConverter<?>> converters = List.class.cast(this.converters.get(targetType));
            if(converters!=null && converters.contains(converter)){
                return;
            }
            List<PropertyConverter<?>> newConverters = new ArrayList<>();
            if (converters != null) {
                newConverters.addAll(converters);
            }
            if(!newConverters.contains(converter)) {
                newConverters.add(converter);
            }
            Collections.sort(newConverters, PRIORITY_COMPARATOR);
            this.converters.put(targetType, Collections.unmodifiableList(newConverters));
            // evaluate transitive closure for all inherited supertypes and implemented interfaces
            // direct implemented interfaces
            for (Class<?> ifaceType : targetType.getRawType().getInterfaces()) {
                converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
                newConverters = new ArrayList<>();
                if (converters != null) {
                    newConverters.addAll(converters);
                }
                newConverters.add(converter);
                Collections.sort(newConverters, PRIORITY_COMPARATOR);
                this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
            }
            Class<?> superClass = targetType.getRawType().getSuperclass();
            while (superClass != null && !superClass.equals(Object.class)) {
                converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(superClass)));
                newConverters = new ArrayList<>();
                if (converters != null) {
                    newConverters.addAll(converters);
                }
                newConverters.add(converter);
                Collections.sort(newConverters, PRIORITY_COMPARATOR);
                this.transitiveConverters.put(TypeLiteral.of(superClass), Collections.unmodifiableList(newConverters));
                for (Class<?> ifaceType : superClass.getInterfaces()) {
                    converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
                    newConverters = new ArrayList<>();
                    if (converters != null) {
                        newConverters.addAll(converters);
                    }
                    newConverters.add(converter);
                    Collections.sort(newConverters, PRIORITY_COMPARATOR);
                    this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
                }
                superClass = superClass.getSuperclass();
            }
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * Allows to evaluate if a given target type is supported.
     *
     * @param targetType the target type, not {@code null}.
     * @return true, if a converter for the given type is registered or a default one can be created.
     */
    public boolean isTargetTypeSupported(TypeLiteral<?> targetType) {
        return converters.containsKey(targetType) || transitiveConverters.containsKey(targetType) || createDefaultPropertyConverter(targetType) != null;
    }

    /**
     * Get a mapProperties of all property converters currently registered. This will not contain the converters that
     * may be created, when an instance is adapted, which provides a String constructor or compatible
     * factory methods taking a single String instance.
     *
     * @return the current mapProperties of instantiated and registered converters.
     * @see #createDefaultPropertyConverter(org.apache.tamaya.TypeLiteral)
     */
    public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
        Lock readLock = lock.readLock();
        try {
            readLock.lock();
            return new HashMap<>(this.converters);
        } finally {
            readLock.unlock();
        }
    }


    /**
     * Get the createList of all current registered converters for the given target type.
     *
     * <p>
     * If no converters are registered, the component tries to createObject and register dynamic
     * converters based on String constructor or static factory methods available.
     * The converters provided are of the following type and returned in the following order:
     * <ul>
     * <li>Converters mapped explicitly to the required target type are returned first, ordered
     * by decreasing priority. This means, if explicit converters are registered these are used
     * primarily for converting a createValue.</li>
     * <li>The target type of each explicitly registered converter can also be transitively mapped to
     * 1) all directly implemented interfaces, 2) all its superclasses (except Object), 3) all the interfaces
     * implemented by its superclasses. This group of transitive converters is returned similarly in the
     * order already mentioned, whereas here a priority based on decreasing ordering is applied.</li>
     * <li>java.lang wrapper classes and native types are automatically mapped.</li>
     * <li>If no explicit converters are registered, for Enum types a default implementation is provided that
     * compares the configuration values with the different enum members defined (case sensitive mapping).</li>
     * </ul>
     * <p>
     * The above createList of directly registered mappings are always tried first, before any transitive mapping
     * should be used. Also in all cases @Priority annotations are honored for ordering of the converters in place.
     * Transitive conversion is supported for all directly implemented interfaces (including inherited ones) and
     * the inheritance hierarchy (exception Object). Superinterfaces of implemented interfaces are ignored.
     *
     * @param targetType the target type, not {@code null}.
     * @param <T>        the type class
     * @return the ordered createList of converters (may be empty for not convertible types).
     * @see #createDefaultPropertyConverter(org.apache.tamaya.TypeLiteral)
     */
    public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
        Lock readLock = lock.readLock();
        List<PropertyConverter<T>> converterList = new ArrayList<>();
        // direct mapped converters
        try {
            readLock.lock();
            addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
            addConvertersToList(List.class.cast(this.transitiveConverters.get(targetType)), converterList);
        } finally {
            readLock.unlock();
        }
        // handling of java.lang wrapper classes
        TypeLiteral<T> boxedType = mapBoxedType(targetType);
        if (boxedType != null) {
            try {
                readLock.lock();
                addConvertersToList(List.class.cast(this.converters.get(boxedType)), converterList);
            } finally {
                readLock.unlock();
            }
        }
        if (converterList.isEmpty() && !TypeLiteral.of(String.class).equals(targetType)) {
            // adding any converters created on the fly, e.g. for enum types.
            PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType);
            if (defaultConverter != null) {
                register(targetType, defaultConverter);
                try {
                    readLock.lock();
                    addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
                } finally {
                    readLock.unlock();
                }
            }
        }
        // check for parametrized types, ignoring param type
        // direct mapped converters
        if(targetType.getType()!=null) {
            try {
                readLock.lock();
                addConvertersToList(List.class.cast(this.converters.get(
                        TypeLiteral.of(targetType.getRawType()))), converterList);
            } finally {
                readLock.unlock();
            }
        }
        return converterList;
    }

    private <T> void addConvertersToList(Collection<PropertyConverter<T>> converters, List<PropertyConverter<T>> converterList) {
        if (converters != null) {
            for(PropertyConverter<T> conv:converters) {
                if(!converterList.contains(conv)) {
                    converterList.add(conv);
                }
            }
        }
    }

    /**
     * Maps native types to the corresponding boxed types.
     *
     * @param targetType the native type.
     * @param <T>        the type
     * @return the boxed type, or null.
     */
    @SuppressWarnings("unchecked")
    private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) {
        Type parameterType = targetType.getType();
        if (parameterType == int.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Integer.class));
        }
        if (parameterType == short.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Short.class));
        }
        if (parameterType == byte.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Byte.class));
        }
        if (parameterType == long.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Long.class));
        }
        if (parameterType == boolean.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
        }
        if (parameterType == char.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Character.class));
        }
        if (parameterType == float.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Float.class));
        }
        if (parameterType == double.class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Double.class));
        }
        if (parameterType == int[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Integer[].class));
        }
        if (parameterType == short[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Short[].class));
        }
        if (parameterType == byte[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Byte[].class));
        }
        if (parameterType == long[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Long[].class));
        }
        if (parameterType == boolean[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Boolean[].class));
        }
        if (parameterType == char[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Character[].class));
        }
        if (parameterType == float[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Float[].class));
        }
        if (parameterType == double[].class) {
            return TypeLiteral.class.cast(TypeLiteral.of(Double[].class));
        }
        return null;
    }

    /**
     * Creates a dynamic {@link PropertyConverter} for the given target type.
     *
     * @param targetType the target type
     * @param <T>        the type class
     * @return a new converters, or null.
     */
    protected <T> PropertyConverter<T> createDefaultPropertyConverter(final TypeLiteral<T> targetType) {
        if (Enum.class.isAssignableFrom(targetType.getRawType())) {
            return new EnumConverter<>(targetType.getRawType());
        }
        PropertyConverter<T> converter = null;
        final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "createValue", "instanceOf", "getInstance", "from", "fromString", "parse");
        if (factoryMethod != null) {
            converter = new DefaultPropertyConverter<>(factoryMethod, targetType.getRawType());
        }
        if (converter == null) {
            final Constructor<T> constr;
            try {
                constr = targetType.getRawType().getDeclaredConstructor(String.class);
            } catch (NoSuchMethodException e) {
                LOG.log(Level.FINEST, "No matching constructor for " + targetType, e);
                return null;
            }
            converter = new PropertyConverter<T>() {
                    @Override
                    public T convert(String value, ConversionContext context) {
                        AccessController.doPrivileged(new PrivilegedAction<Object>() {
                            @Override
                            public Object run() {
                                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                                    @Override
                                    public Object run() {
                                        constr.setAccessible(true);
                                        return null;
                                    }
                                });
                                return null;
                            }
                        });
                        try {
                            return constr.newInstance(value);
                        } catch (Exception e) {
                            LOG.log(Level.SEVERE, "Error creating new PropertyConverter instance " + targetType, e);
                        }
                        return null;
                    }
                };
        }
        return converter;
    }

    /**
     * Tries to evaluate a factory method that can be used to createObject an instance based on a String.
     *
     * @param type        the target type
     * @param methodNames the possible static method names
     * @return the first method found, or null.
     */
    private Method getFactoryMethod(Class<?> type, String... methodNames) {
        Method m;
        for (String name : methodNames) {
            try {
                m = type.getDeclaredMethod(name, String.class);
                return m;
            } catch (NoSuchMethodException | RuntimeException e) {
                LOG.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name);
            }
        }
        return null;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof PropertyConverterManager)) {
            return false;
        }
        PropertyConverterManager that = (PropertyConverterManager) o;
        return converters.equals(that.converters);

    }

    @Override
    public int hashCode() {
        return converters.hashCode();
    }



    /**
     * Default converter implementation performing several lookups for String conversion
     * options.
     * @param <T>
     */
    private static class DefaultPropertyConverter<T> implements PropertyConverter<T> {

        private final Method factoryMethod;
        private final Class<T> targetType;

        DefaultPropertyConverter(Method factoryMethod, Class<T> targetType){
            this.factoryMethod = Objects.requireNonNull(factoryMethod);
            this.targetType =  Objects.requireNonNull(targetType);
        }

        @Override
        public T convert(String value, ConversionContext context) {
            context.addSupportedFormats(getClass(), "<String -> " + factoryMethod.toGenericString());
            if (!Modifier.isStatic(factoryMethod.getModifiers())) {
                throw new ConfigException(factoryMethod.toGenericString() +
                        " is not a static method. Only static " +
                        "methods can be used as factory methods.");
            }
            try {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        factoryMethod.setAccessible(true);
                        return null;
                    }
                });
                Object invoke = factoryMethod.invoke(null, value);
                return targetType.cast(invoke);
            } catch (Exception e) {
                throw new ConfigException("Failed to decode '" + value + "'", e);
            }
        }
    }

}
