/*
 * 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.wayang.core.util;

import org.apache.commons.lang3.Validate;
import org.apache.wayang.core.api.exception.WayangException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Utilities for reflection code.
 */
public class ReflectionUtils {

    private static final Logger logger = LogManager.getLogger(ReflectionUtils.class);

    private static final Pattern defaultConstructorPattern = Pattern.compile(
            "new ([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)\\(\\)"
    );

    private static final Pattern arglessMethodPattern = Pattern.compile(
            "([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)\\.([a-zA-Z_][a-zA-Z0-9_]*)\\(\\)"
    );

    private static final Pattern constantPattern = Pattern.compile(
            "([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)\\.([a-zA-Z_][a-zA-Z0-9_]*)"
    );

    private static final List<Tuple<Class<?>, Supplier<?>>> defaultParameterSuppliers = Arrays.asList(
            new Tuple<>(byte.class, () -> (byte) 0),
            new Tuple<>(Integer.class, () -> (byte) 0),
            new Tuple<>(short.class, () -> (short) 0),
            new Tuple<>(Short.class, () -> (short) 0),
            new Tuple<>(int.class, () -> 0),
            new Tuple<>(Integer.class, () -> 0),
            new Tuple<>(long.class, () -> 0L),
            new Tuple<>(Long.class, () -> 0L),
            new Tuple<>(boolean.class, () -> false),
            new Tuple<>(Boolean.class, () -> false),
            new Tuple<>(float.class, () -> 0f),
            new Tuple<>(Float.class, () -> 0f),
            new Tuple<>(double.class, () -> 0d),
            new Tuple<>(Double.class, () -> 0d),
            new Tuple<>(char.class, () -> '\0'),
            new Tuple<>(Character.class, () -> '\0'),
            new Tuple<>(String.class, () -> "")
    );

    /**
     * Identifies and returns the JAR file declaring the {@link Class} of the given {@code object} or {@code null} if
     * no such file could be determined.
     */
    public static String getDeclaringJar(Object object) {
        Validate.notNull(object);

        return getDeclaringJar(object.getClass());
    }

    /**
     * Identifies and returns the JAR file declaring the given {@link Class} if no such file could be determined.
     */
    public static String getDeclaringJar(Class<?> cls) {
        try {
            final URL location = cls.getProtectionDomain().getCodeSource().getLocation();
            final URI uri = location.toURI();
            final String path = uri.getPath();
            if (path.endsWith(".jar")) {
                return path;
            } else {
                logger.warn("Class {} is not loaded from a JAR file, but from {}. Thus, cannot provide the JAR file.", cls, path);
            }
        } catch (Exception e) {
            logger.error(String.format("Could not determine JAR file declaring %s.", cls), e);
        }
        return null;
    }

    /**
     * Provides a resource as an {@link InputStream}.
     *
     * @param resourceName the name or path of the resource
     * @return an {@link InputStream} with the contents of the resource or {@code null} if the resource could not be found
     */
    public static InputStream loadResource(String resourceName) {
        return Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName);
    }

    /**
     * Provides a resource as {@link URL}.
     *
     * @param resourceName the name or path of the resource
     * @return a {@link URL} describing the path to the resource or {@code null} if the resource could not be found
     */
    public static URL getResourceURL(String resourceName) {
        return Thread.currentThread().getContextClassLoader().getResource(resourceName);
    }

    /**
     * Casts the given {@link Class} to a more specific one.
     *
     * @param baseClass that should be casted
     * @param <T>       the specific type parameter for the {@code baseClass}
     * @return the {@code baseClass}, casted
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> specify(Class<? super T> baseClass) {
        return (Class<T>) baseClass;
    }

    /**
     * Casts the given {@link Class} to a more general one.
     *
     * @param baseClass that should be casted
     * @param <T>       the specific type parameter for the {@code baseClass}
     * @return the {@code baseClass}, casted
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> generalize(Class<? extends T> baseClass) {
        return (Class<T>) baseClass;
    }

    /**
     * Tries to evaluate the given statement, thereby supporting the following statement types:
     * <ul>
     * <li>{@code new <class name>()}</li>
     * <li>{@code <class name>.<constant>}</li>
     * <li>{@code <class name>.<static method>}()</li>
     * </ul>
     *
     * @param statement the statement
     * @param <T>       the return type
     * @return the result of the evaluated statement
     */
    public static <T> T evaluate(String statement) throws IllegalArgumentException {
        statement = statement.trim();
        Matcher matcher = defaultConstructorPattern.matcher(statement);
        if (matcher.matches()) {
            try {
                return instantiateDefault(matcher.group(1));
            } catch (Exception e) {
                throw new IllegalArgumentException(String.format("Could not instantiate '%s'.", statement), e);
            }
        }

        matcher = arglessMethodPattern.matcher(statement);
        if (matcher.matches()) {
            try {
                return executeStaticArglessMethod(matcher.group(1), matcher.group(2));
            } catch (Exception e) {
                throw new IllegalArgumentException(String.format("Could not execute '%s'.", statement), e);
            }
        }

        matcher = constantPattern.matcher(statement);
        if (matcher.matches()) {
            try {
                return retrieveStaticVariable(matcher.group(1), matcher.group(2));
            } catch (Exception e) {
                throw new IllegalArgumentException(String.format("Could not execute '%s'.", statement), e);
            }
        }

        throw new IllegalArgumentException(String.format("Unknown expression type: '%s'.", statement));
    }

    /**
     * Executes a parameterless static method.
     *
     * @param className  the name of the {@link Class} that comprises the method
     * @param methodName the name of the method
     * @param <T>
     * @return the return value of the executed method
     */
    @SuppressWarnings("unchecked")
    public static <T> T executeStaticArglessMethod(String className, String methodName) {
        try {
            final Class<?> cls = Class.forName(className);
            final Method method = cls.getMethod(methodName);
            Validate.isTrue(method.getParameters().length == 0, "Method has parameters.");
            return (T) method.invoke(null);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new IllegalArgumentException(String.format("Could not execute %s.%s().", className, methodName), e);
        }
    }

    /**
     * Retrieves a static variable.
     *
     * @param className    the name of the {@link Class} that comprises the method
     * @param variableName the name of the method
     * @param <T>
     * @return the return value of the executed method
     */
    @SuppressWarnings("unchecked")
    public static <T> T retrieveStaticVariable(String className, String variableName) {
        try {
            final Class<?> cls = Class.forName(className);
            final Field field = cls.getField(variableName);
            return (T) field.get(null);
        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
            throw new IllegalArgumentException(String.format("Could not retrieve %s.%s.", className, variableName), e);
        }
    }

    /**
     * Creates a new instance of a {@link Class} via the default constructor.
     *
     * @param className name of the {@link Class} to be instantiated
     * @return the instance
     */
    public static <T> T instantiateDefault(String className) {
        try {
            @SuppressWarnings("unchecked") // Will fail anyway, if incorrect.
                    Class<T> cls = (Class<T>) Class.forName(className);
            return cls.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new WayangException("Could not instantiate class.", e);
        }
    }

    /**
     * Creates a new instance of the given {@link Class} via the default constructor.
     *
     * @param cls the {@link Class} to be instantiated
     * @return the instance
     */
    public static <T> T instantiateDefault(Class<? extends T> cls) {
        try {
            return cls.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new WayangException("Could not instantiate class.", e);
        }
    }

    /**
     * Tries to instantiate an arbitrary instance of the given {@link Class}.
     *
     * @param cls               that should be instantiated
     * @param defaultParameters designate specific default parameter values for parameter {@link Class}es
     * @return the instance
     */
    @SuppressWarnings("unchecked")
    public static <T> T instantiateSomehow(Class<T> cls, Tuple<Class<?>, Supplier<?>>... defaultParameters) {
        return instantiateSomehow(cls, Arrays.asList(defaultParameters));
    }

    /**
     * Tries to instantiate an arbitrary instance of the given {@link Class}.
     *
     * @param cls               that should be instantiated
     * @param defaultParameters designate specific default parameter values for parameter {@link Class}es
     * @return the instance
     */
    @SuppressWarnings("unchecked")
    public static <T> T instantiateSomehow(Class<T> cls, List<Tuple<Class<?>, Supplier<?>>> defaultParameters) {
        try {
            for (Constructor<?> constructor : cls.getConstructors()) {
                try {
                    final Class<?>[] parameterTypes = constructor.getParameterTypes();
                    Object[] parameters = new Object[parameterTypes.length];
                    for (int i = 0; i < parameterTypes.length; i++) {
                        Class<?> parameterType = parameterTypes[i];
                        Object parameter = getDefaultParameter(parameterType, defaultParameters);
                        if (parameter == null) {
                            parameter = getDefaultParameter(parameterType, defaultParameterSuppliers);
                        }
                        parameters[i] = parameter;
                    }
                    return (T) constructor.newInstance(parameters);
                } catch (Throwable t) {
                    logger.debug("Could not instantiate {}.", cls.getSimpleName(), t);
                }
            }
        } catch (Throwable t) {
            throw new WayangException(String.format("Could not get constructors for %s.", cls.getSimpleName()));
        }

        throw new WayangException(String.format("Could not instantiate %s.", cls.getSimpleName()));
    }

    /**
     * Searches for a compatible {@link Class} in the given {@link List} (subclass or equal) for the given parameter
     * {@link Class}. If a match is found, the corresponding {@link Supplier} is used to create a default parameter.
     *
     * @param parameterClass            {@link Class} of a parameter
     * @param defaultParameterSuppliers supply default values for various parameter {@link Class}es
     * @return the first match's {@link Supplier} value or {@code null} if no match was found
     */
    private static Object getDefaultParameter(Class<?> parameterClass, List<Tuple<Class<?>, Supplier<?>>> defaultParameterSuppliers) {
        for (Tuple<Class<?>, Supplier<?>> defaultParameterSupplier : defaultParameterSuppliers) {
            if (parameterClass.isAssignableFrom(defaultParameterSupplier.getField0())) {
                return defaultParameterSupplier.getField1().get();
            }
        }
        return null;
    }

    /**
     * Retrieve the {@link Type}s of type parameters from an extended/implemented superclass/interface.
     *
     * @param subclass   the {@link Class} implementing the superclass/interface with type parameters
     * @param superclass the superclass/interface defining the type parameters
     * @return a {@link Map} mapping the type parameter names to their implemented {@link Type}
     */
    public static Map<String, Type> getTypeParameters(Class<?> subclass, Class<?> superclass) {
        // Gather implemented interfaces and superclass.
        List<Type> genericSupertypes = Stream.concat(
                Stream.of(subclass.getGenericSuperclass()), Stream.of(subclass.getGenericInterfaces())
        ).collect(Collectors.toList());

        for (Type supertype : genericSupertypes) {

            if (supertype instanceof Class<?>) {
                // If the supertype is a Class, there are no type parameters to worry about.
                Class<?> cls = (Class<?>) supertype;
                if (!superclass.isAssignableFrom(cls)) continue;
                return getTypeParameters(cls, superclass);

            } else if (supertype instanceof ParameterizedType) {
                // Handle type parameters.
                ParameterizedType parameterizedType = (ParameterizedType) supertype;
                final Type rawType = parameterizedType.getRawType();
                if (!(rawType instanceof Class<?>)) continue;
                Class<?> cls = (Class<?>) rawType;
                if (!superclass.isAssignableFrom(cls)) continue;
                final Map<String, Type> localTypeArguments = getTypeArguments(parameterizedType);

                if (cls.equals(superclass)) {
                    // If we reached the superclass, we are good.
                    return localTypeArguments;

                } else {
                    // If we are not there yet, we need to consider to "redirect" type parameters.
                    final Map<String, Type> preliminaryResult = getTypeParameters(cls, superclass);
                    final Map<String, Type> result = new HashMap<>(preliminaryResult.size());
                    for (Map.Entry<String, Type> entry : preliminaryResult.entrySet()) {
                        if (entry.getValue() instanceof TypeVariable<?>) {
                            final Type translatedTypeArgument = localTypeArguments.getOrDefault(
                                    ((TypeVariable) entry.getValue()).getName(),
                                    entry.getValue()
                            );
                            result.put(entry.getKey(), translatedTypeArgument);
                        } else {
                            result.put(entry.getKey(), entry.getValue());
                        }
                    }
                    return result;

                }
            }
        }

        return Collections.emptyMap();
    }

    /**
     * Put the {@link TypeVariable}s of a {@link ParameterizedType} into a {@link Map}.
     *
     * @param type the {@link ParameterizedType}
     * @return the {@link Map} with the type parameter names as keys
     */
    private static Map<String, Type> getTypeArguments(ParameterizedType type) {
        final Type[] typeArguments = type.getActualTypeArguments();
        final Class<?> rawType = (Class<?>) type.getRawType();
        final TypeVariable<? extends Class<?>>[] typeParameters = rawType.getTypeParameters();
        Map<String, Type> result = new HashMap<>(typeArguments.length);
        for (int i = 0; i < typeArguments.length; i++) {
            final TypeVariable<?> typeParameter = typeParameters[i];
            final Type typeArgument = typeArguments[i];
            result.put(typeParameter.getName(), typeArgument);
        }
        return result;
    }

    /**
     * Retrieve a property from an object.
     *
     * @param obj      from which the property should be retrieved
     * @param property the property
     * @param <T>      the return type
     * @return the property
     */
    @SuppressWarnings("unchecked")
    public static <T> T getProperty(Object obj, String property) {
        Class<?> artifactClass = obj.getClass();
        String accessorName = "get" + Character.toUpperCase(property.charAt(0)) + property.substring(1);
        try {
            do {
                final Optional<Method> optMethod = Arrays.stream(artifactClass.getMethods())
                        .filter(method -> method.getName().equals(accessorName))
                        .findAny();
                if (optMethod.isPresent()) {
                    return (T) artifactClass.getMethod(accessorName).invoke(obj);
                }
                artifactClass = artifactClass.getSuperclass();
            } while (artifactClass != null);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(String.format("Could not execute %s() on %s.", accessorName, obj), e);
        }
        throw new IllegalArgumentException(String.format("Did not find method %s() for %s.", accessorName, obj));
    }

    /**
     * Convert the given {@link Object} to a {@code double}.
     *
     * @param o the {@link Object}
     * @return the {@code double}
     */
    public static double toDouble(Object o) {
        if (o instanceof Double) return (Double) o;
        else if (o instanceof Integer) return (Integer) o;
        else if (o instanceof Float) return (Float) o;
        else if (o instanceof Long) return (Long) o;
        else if (o instanceof Short) return (Short) o;
        else if (o instanceof Byte) return (Byte) o;
        else if (o instanceof BigDecimal) return ((BigDecimal) o).doubleValue();
        else if (o instanceof BigInteger) return ((BigInteger) o).doubleValue();
        throw new IllegalStateException(String.format("%s (%s) cannot be retrieved as double.", o,
                o == null ? "unknown class" : o.getClass().getCanonicalName()));

    }


    public static Type getWrapperClass(Type type, int index) {
        if (type != null && (type instanceof ParameterizedType)) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            return parameterizedType.getActualTypeArguments()[index];
        }
        return null;
    }
}
