package cc.smtweb.framework.core.mvc.controller.scan;

import cc.smtweb.framework.core.mvc.config.ControllerConfig;
import cc.smtweb.framework.core.mvc.controller.ApiConfigBean;
import cc.smtweb.framework.core.mvc.controller.MethodAccessManager;
import cc.smtweb.framework.core.mvc.controller.binder.CacheEditor;
import cc.smtweb.framework.core.mvc.controller.binder.WebDataBinder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * 微服务API扫描，扫描生成api接口实现放入methodAccessManager
 *
 * @author xkliu
 */
@Slf4j
public class ApplicationScanner {
    public static void scan(ConfigurableApplicationContext applicationContext) throws Exception {
        MethodAccessManager methodAccessManager = applicationContext.getBean(MethodAccessManager.class);
        BeanManager beanManager = BeanManager.getInstance();
        beanManager.install(applicationContext);

        String[] names = applicationContext.getBeanNamesForType(ControllerConfig.class);
        if (names != null) {
            WebDataBinder webDataBinder = new WebDataBinder(new CacheEditor(methodAccessManager.getCacheManager()));
            ApiConfigBean apiConfig = applicationContext.getBean(ApiConfigBean.class);
            List<ControllerConfig> controllerConfigs = new ArrayList<>();

            ScanContext scanContext = new ScanContext(beanManager, webDataBinder);

            for (String name : names) {
                ControllerConfig controllerConfig = applicationContext.getBean(name, ControllerConfig.class);
                controllerConfigs.add(controllerConfig);

                // 先注册自定义注解解析器
                IScanActionBuilder scanActionBuilder = controllerConfig.getScanActionBuilder();
                if (scanActionBuilder != null) {
                    scanContext.addScanAction(scanActionBuilder.build(applicationContext, webDataBinder));
                }
            }

            for (ControllerConfig controllerConfig : controllerConfigs) {
                scanContext.setModule(controllerConfig.getModule());
                log.info("[/api/{}/*]start scan {}", controllerConfig.getModule(), controllerConfig.getPackagePath());

                // 扫描 Service 类
                PackageScanner packageScanner = new PackageScanner(
                        new ClassParser(new UrlMaker(apiConfig, controllerConfig.getModule()), scanContext));
                packageScanner.scan(controllerConfig.getPackagePath());
            }

            // 单例进行实例化，并设置实例的field(@SwParam)，关联扩展的action(@SwAction)到方法执行器
            beanManager.init();

            log.info("[smt] scan ok.");
        }
        methodAccessManager.init(beanManager, null);
    }
}
