/*
 * 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.johnzon.mapper.access;

import org.apache.johnzon.mapper.Adapter;
import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.JohnzonConverter;
import org.apache.johnzon.mapper.MapperConverter;
import org.apache.johnzon.mapper.ObjectConverter;
import org.apache.johnzon.mapper.internal.ConverterAdapter;
import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;

import java.beans.ConstructorProperties;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import static java.util.Arrays.asList;
import static org.apache.johnzon.mapper.reflection.Converters.matches;

// handle some specific types
public abstract class BaseAccessMode implements AccessMode {
    private static final Type[] NO_PARAMS = new Type[0];

    private final Map<Class<?>, String[]> fieldsToRemove = new HashMap<Class<?>, String[]>();
    private final boolean acceptHiddenConstructor;
    private final boolean useConstructor;

    protected BaseAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) {
        this.useConstructor = useConstructor;
        this.acceptHiddenConstructor = acceptHiddenConstructor;

        // mainly built it in the JVM types == user cant handle them
        fieldsToRemove.put(Throwable.class, new String[]{"suppressedExceptions", "cause"});
    }

    protected abstract Map<String,Reader> doFindReaders(Class<?> clazz);
    protected abstract Map<String,Writer> doFindWriters(Class<?> clazz);

    @Override
    public Comparator<String> fieldComparator(final Class<?> clazz) {
        return null;
    }

    @Override
    public Map<String, Reader> findReaders(final Class<?> clazz) {
        return sanitize(clazz, doFindReaders(clazz));
    }

    @Override
    public Map<String, Writer> findWriters(final Class<?> clazz) {
        return sanitize(clazz, doFindWriters(clazz));
    }

    // editable during builder time, dont do it at runtime or you get no guarantee
    public Map<Class<?>, String[]> getFieldsToRemove() {
        return fieldsToRemove;
    }

    @Override
    public ObjectConverter.Reader<?> findReader(final Class<?> clazz) {
        return null; // TODO: converter?
    }

    @Override
    public ObjectConverter.Writer<?> findWriter(final Class<?> clazz) {
        return null; // TODO: converter?
    }

    @Override
    public Adapter<?, ?> findAdapter(Class<?> clazz) {
        return null; // TODO: converter?
    }

    @Override
    public void afterParsed(final Class<?> clazz) {
        // no-op
    }

    @Override
    public Factory findFactory(final Class<?> clazz) {
        Constructor<?> constructor = null;
        for (final Constructor<?> c : clazz.getDeclaredConstructors()) {
            if (c.getParameterTypes().length == 0) {
                if (!Modifier.isPublic(c.getModifiers()) && acceptHiddenConstructor) {
                    c.setAccessible(true);
                }
                constructor = c;
                if (!useConstructor) {
                    break;
                }
            } else if (c.getAnnotation(ConstructorProperties.class) != null) {
                constructor = c;
                break;
            }
        }
        if (constructor == null) {
            try {
                constructor = clazz.getConstructor();
            } catch (final NoSuchMethodException e) {
                return null; // readOnly class
            }
        }

        final boolean constructorHasArguments = constructor != null && constructor.getGenericParameterTypes().length > 0;
        final Type[] factoryParameterTypes;
        final String[] constructorParameters;
        final Adapter<?, ?>[] constructorParameterConverters;
        final Adapter<?, ?>[] constructorItemParameterConverters;
        if (constructorHasArguments) {
            factoryParameterTypes = constructor.getGenericParameterTypes();

            constructorParameters = new String[constructor.getGenericParameterTypes().length];
            final ConstructorProperties constructorProperties = constructor.getAnnotation(ConstructorProperties.class);
            System.arraycopy(constructorProperties.value(), 0, constructorParameters, 0, constructorParameters.length);

            constructorParameterConverters = new Adapter<?, ?>[constructor.getGenericParameterTypes().length];
            constructorItemParameterConverters = new Adapter<?, ?>[constructorParameterConverters.length];
            for (int i = 0; i < constructorParameters.length; i++) {
                for (final Annotation a : constructor.getParameterAnnotations()[i]) {
                    if (a.annotationType() == JohnzonConverter.class) {
                        try {
                            MapperConverter mapperConverter = JohnzonConverter.class.cast(a).value().newInstance();
                            if (mapperConverter instanceof Converter) {
                                final Adapter<?, ?> converter = new ConverterAdapter((Converter) mapperConverter);
                                if (matches(constructor.getParameterTypes()[i], converter)) {
                                    constructorParameterConverters[i] = converter;
                                    constructorItemParameterConverters[i] = null;
                                } else {
                                    constructorParameterConverters[i] = null;
                                    constructorItemParameterConverters[i] = converter;
                                }
                            } else {
                                throw new UnsupportedOperationException("TODO implement");
                            }
                        } catch (final Exception e) {
                            throw new IllegalArgumentException(e);
                        }
                    }
                }
            }
        } else {
            factoryParameterTypes = NO_PARAMS;
            constructorParameters = null;
            constructorParameterConverters = null;
            constructorItemParameterConverters = null;
        }

        final Constructor<?> cons = constructor;
        if (cons != null && !cons.isAccessible()) {
            cons.setAccessible(true);
        }
        return new Factory() {
            @Override
            public Object create(final Object[] params) {
                if (cons == null) {
                    throw new IllegalArgumentException(clazz.getName() + " can't be instantiated by Johnzon, this is a write only class");
                }
                try {
                    return params == null ? cons.newInstance() : cons.newInstance(params);
                } catch (final InstantiationException e) {
                    throw new IllegalStateException(e);
                } catch (final IllegalAccessException e) {
                    throw new IllegalStateException(e);
                } catch (final InvocationTargetException e) {
                    throw new IllegalStateException(e.getCause());
                }
            }

            @Override
            public Type[] getParameterTypes() {
                return factoryParameterTypes;
            }

            @Override
            public String[] getParameterNames() {
                return constructorParameters;
            }

            @Override
            public Adapter<?, ?>[] getParameterConverter() {
                return constructorParameterConverters;
            }

            @Override
            public Adapter<?, ?>[] getParameterItemConverter() {
                return constructorItemParameterConverters;
            }
        };
    }

    private <T> Map<String, T> sanitize(final Class<?> type, final Map<String, T> delegate) {
        for (final Map.Entry<Class<?>, String[]> entry : fieldsToRemove.entrySet()) {
            if (entry.getKey().isAssignableFrom(type)) {
                for (final String field : entry.getValue()) {
                    delegate.remove(field);
                }
                return delegate;
            }
        }
        return delegate;
    }

    protected Type fixType(final Class<?> clazz, final Type type) { // to enhance
        if (TypeVariable.class.isInstance(type)) { // we need to handle it on deserialization side, not needed on serialization side
            return fixTypeVariable(clazz, type);
        }
        if (ParameterizedType.class.isInstance(type)) {
            final ParameterizedType pt = ParameterizedType.class.cast(type);
            final Type[] actualTypeArguments = pt.getActualTypeArguments();
            if (actualTypeArguments.length == 1 && Class.class.isInstance(pt.getRawType())
                && Collection.class.isAssignableFrom(Class.class.cast(pt.getRawType()))
                && Class.class.cast(pt.getRawType()).getName().startsWith("java.util.")
                && TypeVariable.class.isInstance(actualTypeArguments[0])) {
                return new JohnzonParameterizedType(pt.getRawType(), fixTypeVariable(clazz, actualTypeArguments[0]));
            } else if (actualTypeArguments.length == 2 && Class.class.isInstance(pt.getRawType())
                && Map.class.isAssignableFrom(Class.class.cast(pt.getRawType()))
                && Class.class.cast(pt.getRawType()).getName().startsWith("java.util.")
                && TypeVariable.class.isInstance(actualTypeArguments[1])) {
                return new JohnzonParameterizedType(pt.getRawType(), actualTypeArguments[0], fixTypeVariable(clazz, actualTypeArguments[1]));
            }
        }
        return type;
    }

    private Type fixTypeVariable(final Class<?> clazz, final Type type) {
        final TypeVariable typeVariable = TypeVariable.class.cast(type);
        final Class<?> classWithDeclaration = findClass(clazz.getSuperclass(), typeVariable.getGenericDeclaration());

        if (classWithDeclaration != null) {
            // try to match generic
            final TypeVariable<? extends Class<?>>[] typeParameters = classWithDeclaration.getTypeParameters();
            final int idx = asList(typeParameters).indexOf(typeVariable);
            if (idx >= 0) {

                ParameterizedType pt = findParameterizedType(clazz, classWithDeclaration);
                if (pt != null) {
                    if (pt.getActualTypeArguments().length == typeParameters.length) {
                        return pt.getActualTypeArguments()[idx];
                    }
                }
            }
        }
        return type;
    }

    private Class<?> findClass(final Class<?> clazz, final GenericDeclaration genericDeclaration) {

        if (clazz == genericDeclaration) {
            return clazz;
        }

        final Class<?> superclass = clazz.getSuperclass();
        if (superclass != null && superclass != Object.class) {
            return findClass(superclass, genericDeclaration);
        }

        return null;
    }

    private ParameterizedType findParameterizedType(Class<?> clazz, Class<?> classWithDeclaration) {

        if (clazz == Object.class) {
            return null;
        }

        Type genericSuperclass = clazz.getGenericSuperclass();

        if (genericSuperclass instanceof ParameterizedType &&
            ((ParameterizedType) genericSuperclass).getRawType() == classWithDeclaration) {

                return (ParameterizedType) genericSuperclass;
        }

        return findParameterizedType(clazz.getSuperclass(), classWithDeclaration);
    }
}
