package com.brframework.commonmq.core;

import com.brframework.commonmq.annotation.MQConfig;
import com.brframework.commonmq.annotation.MQListener;
import com.brframework.commonweb.core.SpringContext;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * MQ初始化
 * @author xu
 * @date 2019/9/5 10:42
 */
@Component
@Slf4j
public class MQInitialize implements ApplicationRunner {

    @Autowired(required = false)
    private MQClient client;
    private ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        if(client == null) return;

        //find MQConfig
        Map<String, Object> beansWithAnnotation = SpringContext.getApplicationContext().getBeansWithAnnotation(MQConfig.class);
        for (String key : beansWithAnnotation.keySet()) {
            //find MQListener
            List<Method> methodsListWithAnnotation = MethodUtils.getMethodsListWithAnnotation(
                    AopUtils.getTargetClass(beansWithAnnotation.get(key)), MQListener.class);
            for (Method method : methodsListWithAnnotation) {
                //listener invoke Method
                addMethodListener(method, beansWithAnnotation.get(key));

            }

        }

    }

    /**
     * 添加方法监听
     * @param method
     * @param target
     */
    private void addMethodListener(Method method, Object target){
        MQListener annotation = AnnotationUtils.getAnnotation(method, MQListener.class);
        assert annotation != null;
        client.addListener(annotation.topic(), (channel, msg) -> {
            List<Object> arrayList = Lists.newArrayList();
            arrayList.add(channel.toString());
            arrayList.add(msg);

            try {
                method.invoke(target, arrayList.toArray());
            } catch (Exception e) {
                log.error("消息监听错误", e);
            }
        });
    }
}
