/**
 * Copyright (c) 2016-present, DesDev, Inc.
 * All rights reserved.
 *
 * Official:http://dedeampz.dedecms.com
 *
 * Company:http://www.desdev.cn
 */

const spawn = require('child_process').spawn;
const spawnSync = require('child_process').spawnSync;
$.fn.scrollBottom = function() {
	return $(this).scrollTop($(this)[0].scrollHeight);
};

var DedeAMPZ = {
	LogFileName: path.join(TempDir, 'DedeAMPZ.control.log'),
	currentTime: function() {
		var now = new Date();
		var year = now.getFullYear();
		var month = now.getMonth() + 1;
		var day = now.getDate();
		var hour = now.getHours();
		var minute = now.getMinutes();
		var second = now.getSeconds();
		if (month.toString().length == 1) {
			var month = '0' + month;
		}
		if (day.toString().length == 1) {
			var day = '0' + day;
		}
		if (hour.toString().length == 1) {
			var hour = '0' + hour;
		}
		if (minute.toString().length == 1) {
			var minute = '0' + minute;
		}
		if (second.toString().length == 1) {
			var second = '0' + second;
		}
		var dateTime = year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second;
		return dateTime;
	},
	saveControlLog: function(msg) {
		if (!fs.existsSync(this.LogFileName)) fs.writeFileSync(this.LogFileName, msg + "\r\n", 'utf8');
		return fs.appendFileSync(this.LogFileName, msg + "\r\n", 'utf8');
	},
	getApachePort: function() {
		var ApacheConfigStr = fs.readFileSync(ApacheINI).toString();
		var Port = ApacheConfigStr.match(/Listen (\d+)/)[1];
		return Port;
	},
	getMariadbPort: function() {
		var MariadbConfigStr = fs.readFileSync(MariadbINI).toString();
		var Port = MariadbConfigStr.match(/port([ \t]+)=([ \t]+)(\d+)/)[3];
		return Port;
	},
	clearControlLog: function() {
		var LogFileName = path.join(TempDir, 'DedeAMPZ.log');
		return fs.unlinkSync(this.LogFileName);
	},
	getControlLog: function() {
		if (!fs.existsSync(this.LogFileName)) return '';
		return fs.readFileSync(this.LogFileName).toString();
	},
	checkApacheIsStart: function() {
		try {
			var SCQueryResult = execSync("sc query DedeAMPZ_Apache").toString();
			return SCQueryResult.indexOf("RUNNING") > 0;
		} catch (e) {
			return 0;
		}
	},
	checkApacheIsStop: function() {
		try {
			var SCQueryResult = execSync("sc query DedeAMPZ_Apache").toString();
			return SCQueryResult.indexOf("STOPPED") > 0;
		} catch (e) {
			return 1;
		}
	},
	checkMariadbIsStart: function() {
		try {
			var SCQueryResult = execSync("sc query DedeAMPZ_Mariadb").toString();
			return SCQueryResult.indexOf("RUNNING") > 0;
		} catch (e) {
			return 0;
		}
	},
	checkMariadbIsStop: function() {
		try {
			var SCQueryResult = execSync("sc query DedeAMPZ_Mariadb").toString();
			return SCQueryResult.indexOf("STOPPED") > 0;
		} catch (e) {
			return 1;
		}
	},
	restartApache: function(cb) {
		this.stopApache((info) => {
			if (info.isend) {
				this.startApache(cb);
			}
		});
	},
	startApache: function(cb) {
		if (this.checkApacheIsStart()) {
			var info = $("textarea#showDedeAMPZ");
			var msg = "[" + this.currentTime() + "] Apache服务已经成功启动";
			info.val(info.val() + msg + "\n").scrollBottom();
			this.saveControlLog(msg)
			cb({
				code: -1,
				msg: 'Apache Service is running',
				isend: true
			});
			return;
		}

		if (this.checkApacheIsStop() === true) {
			this.startApacheService(cb);
			return;
		}
		
		var ApachePort = this.getApachePort();
		//console.log(ApachePort);
		Util.checkPort(ApachePort, (isUse) => {
			//console.log('isUse',isUse);
			if (isUse) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Apache端口[" + ApachePort + "]已被占用";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg)
				cb({
					code: -1,
					msg: 'Apache Port is take up',
					isend: true
				});
				return;
			} else {
				var InstallApacheService = spawn(ApacheCli, ["-k", "install", "-n", "DedeAMPZ_Apache", "-f", ApacheINI]);
				InstallApacheService.stdout.on('data', (data) => {
					console.log(data.toString());
					//var info = $("textarea#showDedeAMPZ");
					//info.val(info.val() + data.toString() + "\n");
				});

				InstallApacheService.stderr.on('data', (data) => {
					console.log(data.toString());
					//var info = $("textarea#showDedeAMPZ");
					//info.val(info.val() + data.toString() + "\n");
				});

				InstallApacheService.on('close', (code) => {
					console.log(`InstallApacheService exited with code ${code}`);
					if (code == 0) {
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] Apache服务成功安装";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: 1,
							msg: 'Apache Service install successfull',
							isend: false
						});
						this.startApacheService(cb);
					} else {
						var info = $("textarea#showDedeAMPZ");
						cb({
							code: -2,
							msg: 'Apache Service not install [' + code + ']',
							isend: true
						});
						var msg = "[" + this.currentTime() + "] Apache服务启动失败，错误代码：InstallApacheService[" + code + "]";
						this.saveControlLog(msg);
						info.val(info.val() + msg + "\n").scrollBottom();
					}
				});
			}
		});


	},
	startApacheService: function(cb) {
		var StartApacheService = spawn(ApacheCli, ["-k", "start", "-n", "DedeAMPZ_Apache"]);
		StartApacheService.stdout.on('data', (data) => {
			console.log(data.toString());
		});

		StartApacheService.stderr.on('data', (data) => {
			console.log(data.toString());
		});

		StartApacheService.on('close', (code) => {
			console.log(`StartApacheService exited with code ${code}`);
			if (code == 0) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] 成功启动Apache服务器";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: 2,
					msg: 'Apache Service is running',
					isend: true
				});
			} else {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Apache服务启动失败，错误代码：StartApacheService[" + code + "]";
				this.saveControlLog(msg);
				info.val(info.val() + msg + "\n").scrollBottom();
				cb({
					code: -3,
					msg: 'Apache Service not run [' + code + ']',
					isend: true
				});
			}
		});
	},
	stopApache: function(cb) {
		if (this.checkApacheIsStop()) {
			var info = $("textarea#showDedeAMPZ");
			var msg = "[" + this.currentTime() + "] Apache服务尚未启动，无法停止";
			info.val(info.val() + msg + "\n").scrollBottom();
			this.saveControlLog(msg);
			cb({
				code: -1,
				msg: 'Apache Service is not running',
				isend: true
			});
			return;
		}
		var StopApacheService = spawn(ApacheCli, ["-k", "stop", "-n", "DedeAMPZ_Apache"]);
		StopApacheService.stdout.on('data', (data) => {
			console.log(data.toString());
			//var info = $("textarea#showDedeAMPZ");
			//info.val(info.val() + data.toString() + "\n");
		});

		StopApacheService.stderr.on('data', (data) => {
			console.log(data.toString());
			//var info = $("textarea#showDedeAMPZ");
			//info.val(info.val() + data.toString() + "\n");
		});

		StopApacheService.on('exit', (code) => {
			console.log(`StopApacheService exited with code ${code}`);
			if (code == 0) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Apache服务成功停止";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: 1,
					msg: 'Apache Service is stop',
					isend: false
				});
				var UnInstallApacheService = spawn(ApacheCli, ["-k", "uninstall", "-n", "DedeAMPZ_Apache", ]);
				UnInstallApacheService.stdout.on('data', (data) => {
					console.log(data.toString());
					//var info = $("textarea#showDedeAMPZ");
					//info.val(info.val() + data.toString() + "\n");
				});

				UnInstallApacheService.stderr.on('data', (data) => {
					console.log(data.toString());
					//var info = $("textarea#showDedeAMPZ");
					//info.val(info.val() + data.toString() + "\n");
				});

				UnInstallApacheService.on('exit', (code) => {
					console.log(`UnInstallApacheService exited with code ${code}`);
					if (code == 0) {
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] Apache服务成功卸载";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: 1,
							msg: 'Apache Service is uninstall',
							isend: true
						});
					} else {
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] Apache服务停止失败，错误代码：UnInstallApacheService[" + code + "]";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: -3,
							msg: 'Apache Service not uninstall [' + code + ']',
							isend: true
						});
					}
				});
			} else {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Apache服务停止失败，错误代码：StopApacheService[" + code + "]";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: -2,
					msg: 'Apache Service not stop [' + code + ']',
					isend: true
				});
			}

		});


	},
	restartMariadb: function(cb) {
		this.stopMariadb((info) => {
			if (info.isend) {
				this.startMariadb(cb);
			}
		});
	},
	startMariadb: function(cb) {
		if (this.checkMariadbIsStart()) {
			var info = $("textarea#showDedeAMPZ");
			var msg = "[" + this.currentTime() + "] Mariadb服务已经成功启动";
			info.val(info.val() + msg + "\n").scrollBottom();
			this.saveControlLog(msg);
			cb({
				code: -1,
				msg: 'Mariadb Service is running',
				isend: true
			});
			return;
		}
		if (this.checkMariadbIsStop() === true) {
			this.startMariadbService();
			return;
		}
		
		var MariadbPort = this.getMariadbPort();
		Util.checkPort(MariadbPort, (isUse) => {
			if (isUse) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Mariadb端口[" + MariadbPort + "]已被占用";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg)
				cb({
					code: -1,
					msg: 'Mariadb Port is take up',
					isend: true
				});
				return;
			} else {

				exec(MariadbCli + ' --install DedeAMPZ_Mariadb --defaults-file=' + MariadbINI, (error, stdout, stderr) => {
					if (error) {
						console.error(`exec error: ${error}`);
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] Mariadb服务安装失败";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: -2,
							msg: 'Mariadb Service not installed',
							isend: true
						});
						return;
					}
					var info = $("textarea#showDedeAMPZ");
					var msg = "[" + this.currentTime() + "] 成功安装Mariadb服务器";
					info.val(info.val() + msg + "\n").scrollBottom();
					this.saveControlLog(msg);
					console.log(`stdout: ${stdout}`);
					console.log(`stderr: ${stderr}`);
					cb({
						code: 1,
						msg: 'Mariadb Service install successfull',
						isend: false
					});
					this.startMariadbService(cb);
				});

				return;

			}
		});




	},
	startMariadbService: function(cb) {
		var StartMariadbService = spawn(MariadbCli, ["-k", "start", "-n", "DedeAMPZ_Mariadb"]);
		StartMariadbService.stdout.on('data', (data) => {
			console.log(data.toString());
		});

		StartMariadbService.stderr.on('data', (data) => {
			console.log(data.toString());
		});

		StartMariadbService.on('close', (code) => {
			console.log(`StartMariadbService exited with code ${code}`);
			if (code == 0) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] 成功启动Mariadb服务器";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: 2,
					msg: 'Mariadb Service start successfull',
					isend: true
				});
			} else {
				//fix 尝试net start 启动
				var StartMariadbServiceByNetStart = spawn('net', ["start", "DedeAMPZ_Mariadb"]);
				StartMariadbServiceByNetStart.stdout.on('data', (data) => {
					console.log(data.toString());
				});

				StartMariadbServiceByNetStart.stderr.on('data', (data) => {
					console.log(data.toString());
				});

				StartMariadbServiceByNetStart.on('close', (code) => {
					console.log(`StartMariadbServiceByNetStart exited with code ${code}`);
					if (code == 0) {
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] 成功启动Mariadb服务器";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: 3,
							msg: 'Mariadb Service start by `net start` successfull',
							isend: true
						});
					} else {
						var info = $("textarea#showDedeAMPZ");
						var msg = "[" + this.currentTime() + "] Mariadb服务启动失败，错误代码：StartMariadbService[" + code + "]";
						info.val(info.val() + msg + "\n").scrollBottom();
						this.saveControlLog(msg);
						cb({
							code: -3,
							msg: 'Mariadb Service not start [' + code + ']',
							isend: true
						});
					}
				});


			}
		});
	},
	stopMariadb: function(cb) {
		if (this.checkMariadbIsStop()) {
			var info = $("textarea#showDedeAMPZ");
			var msg = "[" + this.currentTime() + "] Mariadb服务尚未启动，无法停止";
			info.val(info.val() + msg + "\n").scrollBottom();
			this.saveControlLog(msg);
			cb({
				code: -1,
				msg: 'Mariadb Service is not running',
				isend: true
			});
			return;
		}
		var StopMariadbService = spawn('net', ["stop", "DedeAMPZ_Mariadb"]);
		StopMariadbService.stdout.on('data', (data) => {
			console.log(data.toString());
			//var info = $("textarea#showDedeAMPZ");
			//info.val(info.val() + data.toString() + "\n");
		});

		StopMariadbService.stderr.on('data', (data) => {
			console.log(data.toString());
			//var info = $("textarea#showDedeAMPZ");
			//info.val(info.val() + data.toString() + "\n");
		});

		StopMariadbService.on('exit', (code) => {
			console.log(`StopMariadbService exited with code ${code}`);
			if (code == 0) {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Mariadb服务成功停止";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: 1,
					msg: 'Mariadb Service is stoped',
					isend: false
				});
				exec(MariadbCli + ' --remove DedeAMPZ_Mariadb', (error, stdout, stderr) => {
					if (error) {
						console.error(`exec error: ${error}`);
						cb({
							code: -2,
							msg: 'Mariadb Service is not remove',
							isend: true
						});
						return;
					}
					var info = $("textarea#showDedeAMPZ");
					var msg = "[" + this.currentTime() + "] Mariadb服务成功卸载";
					info.val(info.val() + msg + "\n").scrollBottom();
					this.saveControlLog(msg);
					cb({
						code: 2,
						msg: 'Mariadb Service is removed',
						isend: true
					});
				});

				return;
			} else {
				var info = $("textarea#showDedeAMPZ");
				var msg = "[" + this.currentTime() + "] Mariadb服务停止失败，错误代码：StopMariadbService[" + code + "]";
				info.val(info.val() + msg + "\n").scrollBottom();
				this.saveControlLog(msg);
				cb({
					code: -3,
					msg: 'Mariadb Service is not stop',
					isend: true
				});
			}

		});

	},
	getApacheConfigStr: function() {
		return fs.readFileSync(ApacheINI).toString();
	},
	// 检测Apache配置文件是否正确
	testApacheConfigStr: function(callback) {
		var TestApacheConfigStr = spawnSync(ApacheCli, ["-f", ApacheTempINI, '-t']);
		//console.log(TestApacheConfigStr);
		var Result = {
			status: TestApacheConfigStr.status,
			stdout: TestApacheConfigStr.stdout.toString(),
			stderr: TestApacheConfigStr.stderr.toString().trim(),
		};
		return Result;
	},
	testMariadbConfigStr: function(callback) {
		try {
			var TestMariadbConfigStr = spawnSync(MariadbCli, ['--defaults-file=' + MariadbTempINI, '--verbose', '--help']);
			var Result = {
				status: TestMariadbConfigStr.status,
				stdout: TestMariadbConfigStr.stdout.toString(),
				stderr: TestMariadbConfigStr.stderr.toString().trim(),
			}
			return Result;
		} catch (e) {
			var Result = {
				status: 1,
				stdout: '',
				stderr: e.message.trim(),
			}
			return Result;
		}

	},
	testPHPConfigStr: function() {
		return true;
	},
	getPHPConfigStr: function() {
		return fs.readFileSync(PHPINI).toString();
	},
	getMariadbConfigStr: function() {
		return fs.readFileSync(MariadbINI).toString();
	},
	// 还原默认Apache配置
	resetApacheConfig: function() {
		if (!fs.existsSync(ApacheINITemplate) || !fs.existsSync(ApacheVhostsINITemplate)) {
			console.log('Apache配置模板文件丢失,请检查安装包是否完整!');
			return false;
		}
		var ApacheINITPLStr = fs.readFileSync(ApacheINITemplate).toString();
		var ApacheINIStr = this.__parseConfig(ApacheINITPLStr);
		return fs.writeFileSync(ApacheINI, ApacheINIStr);
	},
	// 还原默认PHP配置
	resetPHPConfig: function() {
		if (!fs.existsSync(PHPINITemplate)) {
			console.log('PHP配置模板文件丢失,请检查安装包是否完整!');
			return false;
		}
		var PHPINITPLStr = fs.readFileSync(PHPINITemplate).toString();
		var PHPINIStr = this.__parseConfig(PHPINITPLStr);
		return fs.writeFileSync(PHPINI, PHPINIStr);
	},
	// 还原默认Mariadb配置
	resetMariadbConfig: function() {

	},
	getApacheVersion: function() {
		try {
			var ApacheVersionStr = spawnSync(ApacheCli, ["-v"]);
			return ApacheVersionStr.stdout.toString().match(/Apache\/([\d\.]+)/)[1];
		} catch (e) {
			return 'unknow';
		}
	},
	getMariadbVersion: function() {
		try {
			var MariadbVersionStr = spawnSync(MariadbCli, ["--version"]);
			return MariadbVersionStr.stdout.toString().match(/Ver ([\d\.]+)/)[1];
		} catch (e) {
			return 'unknow';
		}
	},
	getPHPVersion: function() {
		try {
			var PHPVersionStr = spawnSync(PHPCli, ["-v"]);
			return PHPVersionStr.stdout.toString().match(/PHP ([\d\.]+)/)[1];
		} catch (e) {
			return 'unknow';
		}
	}
};