/*
 * 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 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;
import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.wayang.core.api.exception.WayangException;

;

/**
 * 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;
    }
}
