package com.gx.obe;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Properties;

import org.dom4j.Document;
import org.dom4j.Element;
import org.eclipse.core.runtime.Platform;
import org.eclipse.nebula.widgets.grid.Grid;
import org.eclipse.swt.core.SwtConstants;
import org.eclipse.swt.core.listener.LoadingAdatper;
import org.eclipse.swt.core.listener.VerifyPasswordListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import com.gx.obe.business.http.HttpProxyUtil;
import com.gx.obe.common.file.enumeration.FileConstants;
import com.gx.obe.common.file.utils.ParsingXmlUtils;
import com.gx.obe.common.widget.shell.ProgressMessageDialog;
import com.gx.obe.components.core.Constants;
import com.gx.obe.components.core.enumeration.TenderProjectEnum;
import com.gx.obe.config.ConfigActivator;
import com.gx.obe.config.ConfigConstants;
import com.gx.obe.config.utils.PropertiesUtils;
import com.gx.obe.license.LicenseService;
import com.gx.obe.license.LicenseTable;
import com.gx.obe.template.utils.TemplateUtil;
import com.gx.obe.util.utils.DateUtils;
import com.gx.obe.util.utils.FileUtils;
import com.gx.obe.util.utils.ObjectUtils;
import com.gx.obe.util.utils.RuntimeUtils;
import com.gx.obe.util.utils.XmlUtils;
import com.gx.obe.web.entity.SysConfigValue;
import com.gx.obe.web.entity.tender.TenderProjectEntity;
import com.gx.obe.web.service.ProjectRuleService;
import com.gx.obe.web.service.SysConfigValueService;
import com.gx.utils.NowTimeUtils;
import com.swtdesigner.SWTResourceManager;

import common.Logger;
import de.kupzog.ktable.KTable;

public class OnStartInit {
	
	private static String INSTRALL_PATH;
	private static String CONFIG_PROPERTIES = "config.properties";
	private static Logger LOG = Logger.getLogger(OnStartInit.class);
	static {
		INSTRALL_PATH = Platform.getInstallLocation().getURL().getPath();
	}
	
	/**
	 * @Description: 初始化系统配置
	 * terminalType 终类类型 
	 * @author guoyr 
	 */
	public static void initSystemConfig(String terminalType) {
		// 设置代理
		HttpProxyUtil.setProxy();
		
		// 初始化配置文件
		configProperties();
		
		// 初始化系统样式
		initStyle();
		
		// 初始化系统配置
		initConfig();
		
		// 设置当前时间
		NowTimeUtils.run();
		
		initAuthorizationFile();
		
		//初始化项目模板文件
		TemplateUtil.initFileOfTimeVerification();
		
		ParsingXmlUtils.addAnalyPackCodeElementListener((a, b) -> {
			Optional.ofNullable(a).map(t -> t.elementTextTrim("evalMethod")).filter(t -> t.length() == 2).ifPresent(t -> {
				String tenderId = Optional.ofNullable(b).map(TenderProjectEntity::getId).orElse(null);
				new ProjectRuleService().updateEvalMethod(t, TenderProjectEnum.getEvalMethodTypeCN(t), tenderId);
			});
		});
	}
	
	/**
	 * @Description: 初始化插件信息
	 * @author chenxw
	 * @param PLUGIN_ID 
	 */
	public static void initPluginId(String PLUGIN_ID) {
		Constants.SYMBOLIC_NAME = PLUGIN_ID;
	}
	
	
	

	/**
	 * @Description: 系统启动之前还原升级之前的系统配置
	 * @author guoyr
	 */
	private static void configProperties(){
		boolean reLoadProperties = false;
		if(PropertiesUtils.getProperty(ConfigConstants.PRODUCT_TYPE, "").equals("")) {
			String copyProductType = ConfigConstants.PRODUCT_TYPE_FINAL;
			String backupPropertiesPath = null;

			// 获得系统安装的根目录
			final File pluginsFileDir = new File(INSTRALL_PATH);
			if(pluginsFileDir.exists()){
				
				// TODO 第二次升级时可将该功功能删除(解决以前升级时不支持模板替换)
				File tempUpdateTemplateFile = new File(pluginsFileDir.getAbsolutePath() + File.separator + "temp_update");
				if(tempUpdateTemplateFile.exists() && FileUtils.getDirectorySize(tempUpdateTemplateFile) > 0){
					// 如果是模板,则先将本地模板删除,然后覆盖
					FileUtils.delAllFile(pluginsFileDir.getAbsolutePath() + File.separator + "template");
					if(FileUtils.copyFolder(tempUpdateTemplateFile.getAbsolutePath(), pluginsFileDir.getAbsolutePath() + File.separator + "template")){
						FileUtils.delFolder(tempUpdateTemplateFile.getAbsolutePath());
					}
				}
				
				// 如果在根目录存在配置文件,则说明升级过系统,则将升级之前的备份还原到新系统中
				File backupConfigFile = new File(pluginsFileDir.getAbsolutePath().concat(File.separator).concat("backup").concat(File.separator).concat(CONFIG_PROPERTIES));
				if(backupConfigFile.exists()){
					backupPropertiesPath = backupConfigFile.getAbsolutePath();
					Properties properties = PropertiesUtils.loadProperties(backupConfigFile.getAbsolutePath());
					String backupProductType = properties.getProperty(ConfigConstants.PRODUCT_TYPE);
					// 获取升级之前使用的版本类型
					if(null != backupProductType && backupProductType.length() > 0) {
						copyProductType = backupProductType;
					}
				}
			}
		
			// 如果启动是没有指定的版本类理,则需要初始化指定的版本(默认正式版本)
			reLoadProperties = ConfigConstants.copyConfig(copyProductType);
			
			if(null != backupPropertiesPath) {
				// 复制升级之前备份的配置(指定配置)
				PropertiesUtils.copyPropertiesFile(backupPropertiesPath, FileConstants.getPluginPath(ConfigActivator.getDefault()).concat(CONFIG_PROPERTIES), ConfigConstants.COPY_PROPERITES);
				reLoadProperties = true;
			}
		
		}
		if(reLoadProperties) {
			PropertiesUtils.reLoadProperties();
		}
		checkAndUpdateConfigProperties();
	}
	
	/**
	 * @Description: 初始化系统样式
	 * @author guoyr 
	 */
	private static void initStyle () {

		// 设置按钮的默认的背景、前景等配置
		SwtConstants.DEFAULT_G_WIDGETS_BG = SWTResourceManager.getColor(220, 220, 220);
		SwtConstants.DEFAULT_SELECT_BG = ColorConstants.SKIN_SELECTION_BG;
		SwtConstants.DEFAULT_BUTTON_ALPHA = 30;
		SwtConstants.DEFAULT_SKIN_BG = ColorConstants.SKIN_BG;
		SwtConstants.DEFAULT_ACTIVE_BG = ColorConstants.SKIN_ACTIVE_BG;
		SwtConstants.DEFAULT_LINK_FG = ColorConstants.SKIN_BG;
		SwtConstants.DEFAULT_LINK_ACTIVE_FG = ColorConstants.SKIN_ACTIVE_BG;
		SwtConstants.DEFAULT_MENU_ACTIVE_FG = ColorConstants.SKIN_FOREGROUND;
		SwtConstants.DEFAULT_MENU_ACTIVE_BG = ColorConstants.SKIN_BG;
		
//		// 设置grid默认的背景、前景等配置
		Grid.DEFAULT_SELECT_BACKGROUND = ColorConstants.SELECT_BACKGROUND;
		Grid.DEFAULT_EVEN_BACKGROUND = ColorConstants.ENENT_LINE_COLOR;
		Grid.DEFAULT_SELECT_FOREGROUND = ColorConstants.SELECT_FOREGROUND;
		
		// 设置ktable默认的背景、前景等配置
		KTable.DEFAULT_SELECT_BACKGROUND = ColorConstants.SELECT_BACKGROUND;
		KTable.DEFAULT_EVEN_BACKGROUND = ColorConstants.ENENT_LINE_COLOR;
		KTable.DEFAULT_BUTTON_BACKGROUND = ColorConstants.BUTTON_BG;
		KTable.DEFAULT_SELECT_FOREGROUND = ColorConstants.SELECT_FOREGROUND;
	}
	
	/**
	 * @Description: 初始化系统配置
	 * @author guoyr 
	 */
	private static void initConfig() {
		VerifyPasswordListener.PASSWOR_TIPS = PropertiesUtils.getProperty(ConfigConstants.PASSWORD_PATTERN_TIPS,"密码必须包含大小写字母、数字和特殊字符(!@#$%^&*?),且在8~16位之间!");
		VerifyPasswordListener.passwordPattern = PropertiesUtils.getProperty(ConfigConstants.PASSWORD_PATTERN,"^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*?])[0-9a-zA-Z!@#$%^&*?]{8,16}$");
	}

	/**
	 * @Description: 验证产品授权
	 * @param productCertFile
	 * @return
	 */
	private static boolean compareProductAuthorizationFile(File productCertFile, File localLicenseFile) {
		// 产品授权
		if(productCertFile.exists()) {
			com.gx.security.Cert productCert = com.gx.security.CertUtil.readCert(productCertFile.getAbsolutePath());
			
			// 本地授权
			com.gx.security.Cert localCert = com.gx.security.CertUtil.readCert(localLicenseFile.getAbsolutePath());
			//如果产品授权时间比当前本地授权时间长,则使用产品中的授权
			if(null != productCert && null != localCert && productCert.getExpiresDate().after(localCert.getExpiresDate())){
				FileUtils.copy(productCertFile.getAbsolutePath(), localLicenseFile.getAbsolutePath());
				
				// 同时在系统用户目录下也备份一份
				File userRootFile = new File(FileConstants.SYS_USER_ROOT.concat(localLicenseFile.getName()));
				if(userRootFile.exists()){
					userRootFile.delete();
				}
				FileUtils.copy(productCertFile.getAbsolutePath(), userRootFile.getAbsolutePath());
				productCertFile.delete();
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * @Description:检查测试
	 * @author guoyr
	 * @return
	 */
	private static void initAuthorizationFile(){
		File productAuthorizationFile = new File(FileConstants.PRODUCT_ROOT.concat("00-00-00-00-00-00").concat(".cer"));
		File localAuthorizationFile = new File(FileConstants.PRODUCT_ROOT.concat(com.gx.security.CertValidator.getInstance().getSequence()).concat(".cer"));
		
		// 本地已使用授权
		if(localAuthorizationFile.exists()) {
			compareProductAuthorizationFile(productAuthorizationFile, localAuthorizationFile);
		}else {
			// 在用户根目录下去找
			File usrDirLicenseFile = new File(FileConstants.SYS_USER_ROOT.concat(localAuthorizationFile.getName()));
			if(usrDirLicenseFile.exists()){
				// 如果找到,则将用户根目录下的授权文件
				FileUtils.copy(usrDirLicenseFile.getAbsolutePath(), localAuthorizationFile.getAbsolutePath());
			}
			if(localAuthorizationFile.exists()) {
				// 使用系统目录下的授权文件后再根据产品授权文件进行对比
				compareProductAuthorizationFile(productAuthorizationFile, localAuthorizationFile);
				
			}else {
				if(productAuthorizationFile.exists()) {
					FileUtils.copy(productAuthorizationFile.getAbsolutePath(), localAuthorizationFile.getAbsolutePath());
				}
			}
		}
	
	}

	private void getAuthorizationFile(File localAuthorizationFile) {
		com.gx.security.CertValidator certValidator = com.gx.security.CertValidator.getInstance(); 
		LicenseService licenseService = new LicenseService();
		LicenseTable strLicense = licenseService.getLicense(certValidator.getMac(), certValidator.getSequence(), PropertiesUtils.getProperty(ConfigConstants.VERSION, ""));
		if(strLicense != null){
			File file = new File(localAuthorizationFile.getAbsolutePath());
			
			//将生成的license 写入文件
			OutputStreamWriter fw = null;
			BufferedWriter bw = null;
			try {
				if(file.exists()) {
					file.delete();
				}else {
					file.createNewFile();
				}
				fw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
				bw = new BufferedWriter(fw);
				bw.write(strLicense.getAuthorizeCode());
				bw.flush();
			} catch (Exception e) {
			}finally {
				if(null != bw) {
					try {
						bw.close();
					} catch (IOException e) {
					}
				}
				if(null != fw) {
					try {
						fw.close();
					} catch (IOException e) {
					}
				}
			}
		}
	}
	
	/**
	 * @Description: 安装驱动
	 * @author guoyr 
	 */
	public static void installDriver() {
		try {
			LOG.debug("进入初始化程序安装" );
			File driverDir = new File(INSTRALL_PATH.concat(File.separator).concat("drivers"));
			if(driverDir.exists() && driverDir.isDirectory()) {
				LOG.debug("找到程序安装目录"  + driverDir.getAbsolutePath());
				String driversPath = driverDir.getAbsolutePath().concat(File.separator).concat("drivers.xml");
				Document document = XmlUtils.getXmlDocument(driversPath);
				if(null != document){
					
					Shell parentShell = Display.getDefault().getActiveShell();
//					ProgressMessageDialog progressDialog = new ProgressMessageDialog(null != parentShell  ? parentShell : new Shell(), false, -1, new LoadingAdatper() {
//						@Override
//						public void finish(boolean flag) {
//						}
//					});
					new Thread(new Runnable() {
						public void run() {
							// 获得根元素
							Display.getDefault().syncExec(new Runnable() {
								public void run() {
									Element rootElement = document.getRootElement();
									List<?> driverElementList = rootElement.elements();
									if(null != driverElementList) {
										boolean isOpen = false;
										for (Object object : driverElementList) {
											Element driver = (Element) object;
											Element ele = driver.element("installOnStart");
											if(null != ele && "01".equals(ele.getTextTrim())) {
												if(!isOpen) {
													isOpen = true;
											
//													progressDialog.open();
												}
												
//												progressDialog.open();
												String name = driver.elementTextTrim("name");
												String fileName = driver.elementTextTrim("fileName");
												
												File installFile = new File(driverDir.getAbsolutePath().concat(File.separator)+fileName);
												LOG.debug("安装包位置为:" + installFile.getAbsolutePath());
												if(installFile.exists()){
													LOG.debug("正在执行安装操作" + installFile.getAbsolutePath());
//													progressDialog.message("正在安装" + name+"...", 0);
													RuntimeUtils.openFIle(installFile);
//													progressDialog.message(name+"安装结束!", 1);
													LOG.debug("执行安装操作结束" );
													ele.setText("");
												}else {
													LOG.debug("未找到安装软件" + installFile.getAbsolutePath());
//													progressDialog.message("未找到" + name+"驱动文件!", -1);
												}
											}else {
//												MessageDialog.openInformation(new Shell(),"程序标记状态不正确");
												LOG.debug("程序标记状态不正确");
											}
										}
										XmlUtils.createXmlFile(document, driversPath);
										
									}
//									if(!progressDialog.isDisposed()) {
//										progressDialog.close();
//									}
								}
							});
							
//							progressDialog.finish(true);
						}
					}).start();
//					progressDialog.setTitle("正在安装驱动...");
				}
			}
		
		} catch (Exception e) {
		}finally {
			registerOcx();
		}
	}
	
	/**
	 * @Description: 注册插件
	 * @author guoyr 
	 */
	private static void registerOcx() {
		try {
			File driverDir = new File(INSTRALL_PATH.concat(File.separator).concat("ocx_files"));
			if(driverDir.exists() && driverDir.isDirectory()) {
				File registerBatFile = new File(driverDir.getAbsolutePath().concat(File.separator).concat("register.bat"));
				if(null != registerBatFile && registerBatFile.exists()){
					Shell parentShell = Display.getDefault().getActiveShell();
					ProgressMessageDialog progressDialog = new ProgressMessageDialog(null != parentShell  ? parentShell : new Shell(), false, -1, new LoadingAdatper() {
						@Override
						public void finish(boolean flag) {
							// 启动时如果发现有需要注册 的控件,则测试完要将该注册脚本删掉,避免每次启动时注册
							if(!registerBatFile.delete()) {
								registerBatFile.deleteOnExit();
							}
						}
					});
					new Thread(new Runnable() {
						public void run() {
							progressDialog.message("正在注册插件...", 0);
							RuntimeUtils.execFile(registerBatFile.getAbsolutePath());
							progressDialog.finish(true);
						}
					}).start();
					progressDialog.setTitle("正在注册插件...");
					progressDialog.open();
				}
			}
			
		} catch (Exception e) {
		}
	}

	// 启动时检查并升级配置文件
	private static boolean checkAndUpdateConfigProperties() {
		SysConfigValueService sysConfigValueService = new SysConfigValueService();
		Date latestModifyTime = sysConfigValueService.getLatestModifyTime(SysConfigEnum.CONFIG_PROPERTIES);
		if(null != latestModifyTime) {
			Date configPropertiesUpdateTime = null;
			String timeStr = PropertiesUtils.getProperty(ConfigConstants.CONFIG_PROPERTIES_UPDATE_TIEM, "");
			if(timeStr.length() >= 10) {
				configPropertiesUpdateTime = DateUtils.toDate(timeStr);
			}
			if(null == configPropertiesUpdateTime || latestModifyTime.after(configPropertiesUpdateTime)) {
				List<SysConfigValue> configValueList = sysConfigValueService.getConfigValueListByConfigCode(SysConfigEnum.CONFIG_PROPERTIES);
				if(null != configValueList && configValueList.size() > 0) {
					for(SysConfigValue sysConfigValue : configValueList) {
						PropertiesUtils.setPropertyValue(sysConfigValue.getConfigValueCode(), ObjectUtils.getObjString(sysConfigValue.getConfigValue()));
					}
					PropertiesUtils.saveProperty(ConfigConstants.CONFIG_PROPERTIES_UPDATE_TIEM, DateUtils.getTimestampFormat(latestModifyTime));
					return true;
				}
			}
		}
		return false;
	}
}