package cn.com.yict.framemax.core.spring.rest;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class RestParameterNameDiscoverer extends DefaultParameterNameDiscoverer implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public String[] getParameterNames(Method method) {
        Class<?> clazz = method.getDeclaringClass();
        if (!clazz.isInterface()) {
            return super.getParameterNames(method);
        }
        clazz = detectClass(clazz);
        clazz = ClassUtils.getUserClass(clazz);
        if (clazz != null) {
            try {
                Method beanMethod = clazz.getMethod(method.getName(), method.getParameterTypes());
                return super.getParameterNames(beanMethod);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return super.getParameterNames(method);
    }

    private Class<?> detectClass(Class<?> clazz) {
        String[] beanNames = applicationContext.getBeanNamesForType(clazz);
        if ((beanNames == null || beanNames.length == 0) && applicationContext.getParent() != null) {
            beanNames = applicationContext.getParent().getBeanNamesForType(clazz);
            if (beanNames != null && beanNames.length > 0) {
                return this.applicationContext.getParent().getType(beanNames[0]);
            }
            return null;
        } else {
            return this.applicationContext.getType(beanNames[0]);
        }
    }

    @Override
    public String[] getParameterNames(Constructor<?> ctor) {
        return super.getParameterNames(ctor);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}
