/*
 * CommandParser.cpp
 *
 *  Created on: Mar 4, 2025
 *      Author: ZhangChundi
 */

#include "CommandParser.h"
#include <thread>

const std::string EMPTY = "";
// 初始化变量
HINSTANCE hLib = nullptr;

// 控制函数在运行的时候，如果用户点击了停止，则退出函数调用
bool exitFunc = false;

////////////////////初始化和定义命令///////////////////
CommandParser::CommandParser(DriverCommon common) :
		common(common) {
	// 注册合法命令（后续加新命令直接往这里append就行）
	validCommands = { "gk -p load", "gk -p unload", "gk -p run", "gk -p stop" };
}

CommandType CommandParser::string2command(const std::string &cmd) {
	if (cmd == validCommands[0])
		return LOAD;
	if (cmd == validCommands[1])
		return UNLOAD;
	if (cmd == validCommands[2])
		return RUN;
	if (cmd == validCommands[3])
		return STOP;
	return UNKNOWN;
}

///////////////////////解析命令/////////////////////
/**
 * 解析用户输入的命令然后封装到ParsedCommand对象里面
 */
bool CommandParser::parse(const std::string &input,
		ParsedCommand &result) const {
	static const std::regex cmdRegex(R"(^\d+\^gk\s-\w+\s\w+(\s.*)?$)");
	if (!std::regex_match(input, cmdRegex)) {
		std::cerr << "Invalid command: " << input << std::endl;
		return false;
	}

	// 分割序号和命令体
	size_t splitPos = input.find('^');
	if (splitPos == std::string::npos) {
		return false;
	}
	result.number = input.substr(0, splitPos);
	std::string commandPart = input.substr(splitPos + 1);

	// 拆词
	std::istringstream iss(commandPart);
	std::vector<std::string> tokens;
	std::string token;
	while (iss >> token) {
		tokens.push_back(token);
	}
	if (tokens.size() < 3) {
		std::cerr << "Command format is error: " << commandPart << std::endl;
		return false;
	}

	result.fullCommand = tokens[0] + " " + tokens[1] + " " + tokens[2];
	for (size_t i = 3; i < tokens.size(); ++i) {
		result.args.push_back(tokens[i]);
	}
	return true;
}

bool CommandParser::isValidCommand(const std::string &cmd) const {
	if (std::find(validCommands.begin(), validCommands.end(), cmd)
			!= validCommands.end()) {
		// 找到了
		return true;
	} else {
		return false;
	}
}

/**
 * 命令目前不对，加载、卸载、运行、停止几条
 * 1.解析命令结构，管道返回命令序号
 * 2.加载DLL
 * 3.解析Flow文件然后调用函数、再把对象通过测试流程末尾函数传回
 * @parameter command 客户端写入到管道的字符串解析生成的命令对象
 */
int CommandParser::handleCommand(ParsedCommand &command) {
	int isSuccess = ErrorType::TYPE_SUCCESS;
	std::string &commandHeader = command.fullCommand;
	switch (string2command(commandHeader)) {
	case LOAD:
		isSuccess = loadDll(command.args);
		break;
	case UNLOAD:
		//{
		//	PrjExit prjExit = (PrjExit) GetProcAddress(
		//						hLib, "prj_exit");
		//	if (!prjExit) {
		//		return ErrorType::LOSE_PRJ_EXIT_FUNCTION;
		//	}
		//	prjExit();
		//}
		// 释放DLL
		FreeLibrary(hLib);
		dllFilePath = EMPTY;
		break;
	case RUN:
		// 运行函数的时候需要开启一个线程，如果用户发送停止命令则停止运行
		isSuccess = runDll(command);
		break;
	case STOP:
		// 如果用户发送停止命令则退出函数调用
		isSuccess = stopDll();
		break;
	default:
		break;
	}
	return isSuccess;
}

///////////////////////命令业务/////////////////////
/**
 * 加载测试工程编译出的DLL文件
 * TODO 可能还要传递一个Header和Execute Mode的信息
 */
int CommandParser::loadDll(const std::vector<std::string> args) {
	// 两个参数，一个DLL路径，一个Flow文件路径
	if (args.size() != 2) {
		return ErrorType::TYPE_THE_COMMAND_PARAMETER_WAS_ERROR;
	}
	std::string dllName = args[0];
	auto result = common.analysisFlowFile(args[1]);
	if (!result) {
		//printErr("Flow file not exist.");
		return ErrorType::TYPE_FLOW_FILE_OR_FORMAT_EXIST_ERROR;
	} else {
		flowMessage = *result;  // 取出真正的对象
	}
	// gk -p load D:/develop/eclipse/runtime-develop.ui.product/testc/build/testc.dll
	// 1^gk -p load D:/develop/eclipse/runtime-develop.ui.product/gsignaldefine/Debug/libgsignaldefine.dll
	dllFilePath = dllName;

	if (dllFilePath == EMPTY) {
		//printString("Please load G-Project first.");
		return ErrorType::TYPE_PLEASE_LOAD_G_PROJECT_FIRST;
	}
	// 加载动态库并执行
	hLib = LoadLibrary(dllFilePath.c_str());
	if (hLib == NULL) {
		DWORD err = GetLastError();
		std::cout << err << std::endl;
		//printString("LoadLibrary was failed.");
		return ErrorType::TYPE_LOAD_LIBRARY_WAS_FAILED;
	}

	// 调用Prj_init函数
	PrjInit prjInit = (PrjInit) GetProcAddress(
					hLib, "prj_init");
	if (!prjInit) {
		return ErrorType::LOSE_PRJ_INIT_FUNCTION;
	}
	prjInit();
	return ErrorType::TYPE_SUCCESS;
}

//////////////////////////////////////////
void CommandParser::executeAllFunc(const Configure& configure) {
	// 有一个循环前先执行的函数，每次循环最先执行，固定函数名、返回值类型和参数
	FlowMessage flowMessage = configure.flowMessage;
	std::vector<TestItem> testItems = flowMessage.testItems;
	for(TestItem testItem : testItems) {
		// 如果没有勾选执行则跳过
		if (!testItem.select) {
			continue;
		}
		std::string funcName = testItem.funcName;
		FunctionTypeStr sharedFunction = (FunctionTypeStr) GetProcAddress(
				hLib, funcName.c_str());
		if (!sharedFunction) {
			std::cerr << "Failed to get function address" << std::endl;
			continue;
		}
		bool result = sharedFunction(configure);
		Setting setting = configure.setting;
		ExecuteSetting executeSetting = setting.executeSetting;
		if (executeSetting.failstop && !result) {
			break;
		}
	}
}

// 每次接收到运行指令都将执行条件设置为false
void CommandParser::executeLoopAllFunc(const Configure& configure, const std::string number) {
	exitFunc = false;

	DUTSetting dutSetting = configure.setting.dutSetting;
	ExecuteSetting executeSetting = configure.setting.executeSetting;
	int loop = executeSetting.loopcount;
	if (loop == 0) {
		// 所有函数一直执行，知道用户点击了Stop
		while(!exitFunc) {
			bool isOk = callFuncs(configure, dutSetting);
			if (!isOk) {
				break;
			}
		}
	} else {
		int loop = executeSetting.loopcount;
		for (int i = 0; i < loop; i++) {
			if (exitFunc) {
				break;
			}
			bool isOk = callFuncs(configure, dutSetting);
			if (!isOk) {
				break;
			}
		}
		// 有一个循环前后执行的函数，每次循环最后执行，固定函数名、返回值类型和参数
	}
	// TODO 函数执行结束，告诉调用者
	printString(number, '^', "execute done");
}

/**
 * 运行测试工程中的函数
 */
int CommandParser::runDll(ParsedCommand &command) {
	const std::vector<std::string> args = command.args;
	if (args.size() != 1) {
		return ErrorType::TYPE_THE_COMMAND_PARAMETER_WAS_ERROR;
	}
	// 解析运行条件
	auto settingOptional = common.analysisSettingFile(args[0]);
	if (!settingOptional) {
		//printErr("Setting file not exist.");
		return ErrorType::TYPE_SETTING_FILE_OR_FORMAT_EXIST_ERROR;
	} else {
		setting = *settingOptional;  // 取出真正的对象
	}
	// 拿到所有函数，目前函数返回值类型都是boolean，参数只有一个FlowMessage类型
	// 有一个最先执行的函数，只执行一次，固定函数名、返回值类型和参数
	std::string commandNumber = command.number;
	std::thread([this, commandNumber]() {
		Configure configure(flowMessage, this->setting);
		this->executeLoopAllFunc(configure, commandNumber);
	}).detach();
	std::cout << "executeLoop execute" << std::endl;
	// 有一个最后执行的函数，只执行一次，固定函数名、返回值类型和参数
	return ErrorType::TYPE_SUCCESS;
}

int CommandParser::stopDll() {
	// 只有在退出条件是false的情况下才修改为true
	exitFunc = true;
	return ErrorType::TYPE_SUCCESS;
}

int CommandParser::testStart(const DUTSetting &dutSetting) {
	TestStart start = (TestStart) GetProcAddress(
						hLib, "test_start");
	if (!start) {
		return ErrorType::LOSE_TEST_START_FUNCTION;
	}
	start(dutSetting);
	return ErrorType::TYPE_SUCCESS;
}

int CommandParser::testEnd() {
	TestEnd end = (TestEnd) GetProcAddress(
						hLib, "test_end");
	if (!end) {
		return ErrorType::LOSE_TEST_END_FUNCTION;
	}
	end();
	return ErrorType::TYPE_SUCCESS;
}

bool CommandParser::callFuncs(const Configure& configure, const DUTSetting &dutSetting) {
	int errorCode = testStart(dutSetting);
	if (errorCode != ErrorType::TYPE_SUCCESS){
		return false;
	}
	executeAllFunc(configure);
	errorCode = testEnd();
	if (errorCode != ErrorType::TYPE_SUCCESS){
		return false;
	}
	return true;
}
//////////////////////命令业务结束////////////////////

