package org.apache.felix.dm.lambda.impl;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.lambda.callbacks.SerializableLambda;

/**
 * Various helper methods related to generics and lambda expressions.
 */
public class Helpers {
	private final static Pattern LAMBDA_INSTANCE_METHOD_TYPE = Pattern.compile("(L[^;]+)+");

	/**
	 * Gets the class name of a given object.
	 * @param obj the object whose class has to be returned.
	 */
	public static Class<?> getClass(Object obj) {
		Class<?> clazz = obj.getClass();
		if (Proxy.isProxyClass(clazz)) {
			return Proxy.getProxyClass(clazz.getClassLoader(), clazz);
		}
		return clazz;
	}
	
	/**
	 * Extracts the type of a given generic lambda parameter.
	 * Example: for "BiConsumer<String, Integer>", and with genericParamIndex=0, this method returns java.lang.String class.
	 * 
	 * @param lambda a lambda expression, which must extends @link {@link SerializableLambda} interface.
	 * @param genericParamIndex the index of a given lambda generic parameter.
	 * @return the type of the lambda generic parameter that corresponds to the <code>genericParamIndex</code>  
	 */
	@SuppressWarnings("unchecked")
    public static <T> Class<T> getLambdaArgType(SerializableLambda lambda, int genericParamIndex) {
	    String[] lambdaParams = getGenericTypeStrings(lambda);
	    Class<?> clazz;
        try {
            clazz = lambda.getClass().getClassLoader().loadClass(lambdaParams[genericParamIndex]);
        } catch (ClassNotFoundException e) {
           throw new RuntimeException("Can't load class " + lambdaParams[genericParamIndex]);
        }
	    return (Class<T>) clazz;
	}
	
	/**
	 * Extracts the first parameter of a lambda.
	 */
	public static String getLambdaParameterName(SerializableLambda lambda, int index) {
		SerializedLambda serialized = getSerializedLambda(lambda);
		Method m = getLambdaMethod(serialized, lambda.getClass().getClassLoader());
		Parameter p = m.getParameters()[index];
		
        if (Objects.equals("arg0", p.getName())) {
            throw new IllegalStateException("Can'f find lambda method name (Please check you are using javac -parameters option).");
        }
        return p.getName();
	}
	
	/**
	 * Returns the SerializedObject of a given lambda.
	 */
    private static SerializedLambda getSerializedLambda(SerializableLambda lambda) {
	    if (lambda == null) {
	        throw new IllegalArgumentException();
	    }

	    for (Class<?> clazz = lambda.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
	        try {
	            Method replaceMethod = clazz.getDeclaredMethod("writeReplace");
	            replaceMethod.setAccessible(true);
	            Object serializedForm = replaceMethod.invoke(lambda);

	            if (serializedForm instanceof SerializedLambda) {
	                return (SerializedLambda) serializedForm;
	            }
	        }
	        catch (NoSuchMethodException e) {
	            // fall through the loop and try the next class
	        }
	        catch (Throwable t) {
	            throw new RuntimeException("Error while extracting serialized lambda", t);
	        }
	    }

	    throw new RuntimeException("writeReplace method not found");
	}

    /**
     * Finds a composite
     * @param component
     * @param type
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <U> U findCompositeInstance(Component component, Class<U> type) {
        U instance = (U) Stream.of(component.getInstances())
            .filter(inst -> Objects.equals(Helpers.getClass(inst), type))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("Did not find a component instance matching type " + type));
        return instance;                       
    }

    /**
     * Extracts the actual types of all lambda generic parameters.
     * Example: for "BiConsumer<String, Integer>", this method returns ["java.lang.String", "java.lang.Integer"].
     */
    private static String[] getGenericTypeStrings(SerializableLambda lambda) {
        // The only portable way to get the actual lambda generic parameters can be done using SerializedLambda.
        SerializedLambda sl = getSerializedLambda(lambda);
        String lambdaMethodType = sl.getInstantiatedMethodType();
        Matcher m = LAMBDA_INSTANCE_METHOD_TYPE.matcher(lambdaMethodType);
        List<String> results = new ArrayList<>();
        while (m.find()) {
            results.add(m.group().substring(1).replace("/", "."));
        }
        return results.toArray(new String[0]);
    }
    
    /**
     * Extracts the actual java method from a given lambda.
     */
    private static Method getLambdaMethod(SerializedLambda lambda, ClassLoader loader) {
        String implClassName = lambda.getImplClass().replace('/', '.');
        Class<?> implClass;
        try {
            implClass = loader.loadClass(implClassName);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Lambda Method not found (can not instantiate class " + implClassName);
        }

        return Stream.of(implClass.getDeclaredMethods())
            .filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName()))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("Lambda Method not found"));
    }
    
}
