package cn.hmsoft.frame.module;

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

import cn.hmsoft.application.AppHelper;
import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.frame.constants.FrameStatus;
import cn.hmsoft.frame.data.dao.FrameModuleDao;
import cn.hmsoft.frame.data.model.FrameModule;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;

/**********************
 * 模块化组件加载工具
 * 
 * @author zxq
 * @create 2018-05-10 13:07:53
 * @version 5.0.0
 * @email: revisit@126.com
 * @Company: www.hmsoft.cn
 */
public final class FrameModuleUtil {

	private static List<FrameModuleConfig> FrameModuleConfigArray = null;

	private static FrameModuleUtil util = null;

	private FrameModuleUtil() {
		FrameModuleConfigArray = new ArrayList<FrameModuleConfig>();
	}

	public static FrameModuleUtil getInstance() {
		if (util == null) {
			synchronized (FrameModuleUtil.class) {
				if (util == null)
					util = new FrameModuleUtil();
			}
		}
		return util;
	}

	/************************
	 * 加载数据所有模块
	 */
	public void loadModule() {
		synchronized (FrameModuleUtil.class) {
			FrameModuleConfigArray = new ArrayList<FrameModuleConfig>();
			try {
				for (FrameModule module : SpringHelper.getBean(FrameModuleDao.class).listModule(AppHelper.AppName)) {
					if (module.getModule_status().equals(FrameStatus.Active.toString())) {
						FrameModuleConfig config = this.loadModule(module);
						if (config != null) {
							FrameModuleConfigArray.add(config);
							LogHelper.log("frame module [" + module.getModule_name() + "] load complete，version ["
									+ module.getModule_version() + "]");
						}
					}
				}
			} catch (Exception ex) {
				LogHelper.error(ex);
			}
		}

	}

	/***************************************
	 * 加载一个模块
	 * 
	 * @param module
	 */
	public FrameModuleConfig loadModule(FrameModule module) {
		if (module == null)
			return null;
		if (module.getModule_id() == null) {
			LogHelper.warn("frame module [" + module.getModule_name() + "] load error：module id not config");
			return null;
		}
		if (StringHelper.isEmpty(module.getModule_name()) || StringHelper.isEmpty(module.getModule_version())) {
			LogHelper.warn("frame module [" + module.getModule_name() + "] load error：module param not config");
			return null;
		}
		FrameModuleConfig loader = null;
		synchronized (FrameModuleUtil.class) {
			try {
				loader = (FrameModuleConfig) Class.forName(module.getModule_class()).newInstance();
				// 设置参数
				if (StringHelper.isNotEmpty(module.getModule_param())) {
					module.prepareParamMap();
				}
			} catch (Exception e) {
				LogHelper.warn(e.getMessage());
				LogHelper.warn("frame module [" + module.getModule_name() + "] load error：module class config error");
			}
			if (loader == null)
				return null;

			if (loader.load(module))
				return loader;
			return null;
		}
	}

	/*************************
	 * 重启一个模块
	 */
	public boolean reloadModule(FrameModule module) {

		if (module == null)
			return false;
		if (module.getModule_id() == null) {
			LogHelper.warn("frame module [" + module.getModule_name() + "] load error：module id not config");
			return false;
		}
		if (StringHelper.isEmpty(module.getModule_name()) || StringHelper.isEmpty(module.getModule_version())) {
			LogHelper.warn("frame module [" + module.getModule_name() + "] load error：module param not config");
			return false;
		}

		synchronized (FrameModuleUtil.class) {
			FrameModuleConfig loader = null;
			for (FrameModuleConfig config : FrameModuleConfigArray) {
				if (config.getModule().getModule_id() - module.getModule_id() == 0) {
					loader = config;
					break;
				}
			}
			// 之前没启动过
			if (loader == null) {
				if (module.getModule_status().equals(FrameStatus.Active.toString()))
					return false;
				loader = this.loadModule(module);
				if (loader != null) {
					if (FrameModuleConfigArray == null)
						FrameModuleConfigArray = new ArrayList<FrameModuleConfig>();
					FrameModuleConfigArray.add(loader);
					return true;
				}
				return false;

			} else {
				try {
					if (module.getModule_status().equals(FrameStatus.Active.toString()))
						return loader.reload();
					else
						return loader.stop();
				} catch (Exception e) {

				}
				return false;

			}
		}
	}

	/************************
	 * 重新加载所有已经运行模块
	 */
	public void reloadModuleFromRunning() {
		synchronized (FrameModuleUtil.class) {
			for (FrameModuleConfig config : FrameModuleConfigArray) {
				try {
					config.reload();
				} catch (Exception e) {

				}
			}
		}
	}

	/************************
	 * 从数据库重新加载
	 */
	public void reloadModuleFomConfig() {
		synchronized (FrameModuleUtil.class) {
			for (FrameModuleConfig config : FrameModuleConfigArray) {
				try {
					config.stop();
				} catch (Exception e) {

				}
			}
			this.loadModule();
		}
	}
}
