package com.wecloud.im.ws.strategy;

import com.google.common.collect.Maps;
import com.wecloud.im.ws.annotation.ReceiveTypeAnnotation;
import com.wecloud.im.ws.enums.WsRequestCmdEnum;
import com.wecloud.im.ws.utils.ClassScanner;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;

/**
 * @Description 策略 bean注解扫描注册类
 * 扫描自定义注解，将指令码与实现类绑定，将对应关系添加到上下文对象中
 * <p>
 * BeanStrategyProcessor是spring在容器初始化后对外暴露的扩展点，
 * spring ioc容器允许beanFactoryPostProcessor在容器加载注册BeanDefinition后读取BeanDefinition，并能修改它。
 * @Author hewei hwei1233@163.com
 * @Date 2020-01-02
 */
@Component
public class ReceiveStrategyProcessor implements BeanFactoryPostProcessor {

    // 扫码注解的包路径
    private static final String STRATEGY_PACK = "com.wecloud.im.ws.strategy.concrete";

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        Map<WsRequestCmdEnum, Class> handlerMap = Maps.newHashMapWithExpectedSize(5);

        // 扫码ReceiveTypeAnnotation注解的类
        Set<Class<?>> classSet = ClassScanner.scan(STRATEGY_PACK, ReceiveTypeAnnotation.class);

        classSet.forEach(clazz -> {
            // 获取注解中的类型值，与枚举类一一对应
            WsRequestCmdEnum type = clazz.getAnnotation(ReceiveTypeAnnotation.class).type();
            handlerMap.put(type, clazz);
        });


        // 初始化Contenxt， 将其注册到spring容器当中
        ReceiveStrategyContext context = new ReceiveStrategyContext(handlerMap);

        try {
            configurableListableBeanFactory.registerResolvableDependency(Class.forName(ReceiveStrategyContext.class.getName()), context);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
