package com.brilliance.mda.runtime.mda.driver.compile;

import com.brilliance.mda.runtime.annotation.Module;
import com.brilliance.mda.runtime.annotation.Transaction;
import com.brilliance.mda.runtime.mda.driver.MdaScanner;
import com.brilliance.mda.runtime.mda.driver.compile.processor.ModuleAnnotationProcess;
import com.brilliance.mda.runtime.mda.driver.compile.processor.TransAnnotationProcessor;
import com.brilliance.mda.support.td.ModuleInfoManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

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

@Component
public class EmitterFactory implements InitializingBean {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Value("${envconfig.emitter.scanPackages:com.ceb.gjjs.mda.manager,com.ceb.gjjs.mda.bo}")
    private String scanPackage;

    @Autowired
    private MdaScanner scanner;

    public void buildEmitter(String... transPack){
        try {
            log.debug("prepare to walk transaction");
            Map<Class<?>, Set<Class<?>>> map = new HashMap<>();
            for (String pack : transPack) {
                scanner.doScan(map, pack.trim().replaceAll("\\.", "/"), Module.class, Transaction.class);
            }
            log.debug("get all modules and transactions");
            Set<Class<?>> moduleSet = map.get(Module.class);
            moduleSet.forEach(item -> {
                try {
                    ModuleInfoManager.getModuleInfo(item.getSimpleName());
                    ModuleInfoManager.loadModuleInfo(item);
                } catch (Exception ignore) {
                }
            });

            Set<Class<?>> transSet = map.get(Transaction.class);
            transSet.forEach(item->new TransAnnotationProcessor().buildTransEmitter(item,scanner.getBeanDefinitionRegistry()));
            ModuleAnnotationProcess.reduceCache();
            TransAnnotationProcessor.getProcessQueue().clear();
            log.debug("walk transaction finished");
            //log.info("注册TableMeta {}个", TableMetaManager.getTableMetaCount());
            log.info("注册ModuleInfo {}个", ModuleInfoManager.getModuleInfoCount());
            log.info("注册Transaction {}个", transSet.size());
        } catch (Exception e) {
            log.error("动态Emitter扫描包发生错误", e);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("动态Emitter扫描包:{}", scanPackage);
        String[] scanPackages = scanPackage.split(",");
        this.buildEmitter(scanPackages);
    }
}
