/*
 * appmysql.cpp
 *
 *  Created on: Oct 14, 2025
 *      Author: user
 */

#include "sqlite3.h"

#include "cardinal825.h"

#include "../appinfo.h"
#include "../apphelpers.h"
#include "appdatabase.h"

using namespace std;

enum { DB_CFG_MODE = 21,
	DB_CFG_SERVER,
	DB_CFG_SERVER2,
	DB_CFG_USER,
	DB_CFG_PASSWORD,
	DB_CFG_DATABASE
};

void CAppDatabaseCfg::UpdateConfigForm(CForm *pForm)
{
	AppDbType mode = appDataSQLite;

	CFormInput *pMode = dynamic_cast<CFormInput*>(pForm->GetItemByIDVal(DB_CFG_MODE));
	if(pMode != nullptr) {
		mode = static_cast<AppDbType>(pMode->GetSelItem());
	}

	if(mode == appDataMySQL || mode == appDataMSSQL) {
		pForm->ShowItem(DB_CFG_SERVER);
		pForm->ShowItem(DB_CFG_SERVER2);
		pForm->ShowItem(DB_CFG_USER);
		pForm->ShowItem(DB_CFG_PASSWORD);
		pForm->ShowItem(DB_CFG_DATABASE);
	} else {
		pForm->HideItem(DB_CFG_SERVER);
		pForm->HideItem(DB_CFG_SERVER2);
		pForm->HideItem(DB_CFG_USER);
		pForm->HideItem(DB_CFG_PASSWORD);
		pForm->HideItem(DB_CFG_DATABASE);
	}
}

EVENT(ConfigMySQLShow)
{
	ClearScreenAndShowTitle(pForm, "Database Configuration");
	return 0;
}

EVENT(DatabaseModeChg)
{
	CAppDatabaseCfg* p = static_cast<CAppDatabaseCfg*>(pForm->GetUserStruct());
	if(p != nullptr) {
		p->UpdateConfigForm(pForm);
	}

	return 0;
}

int show_db_callback(char* response, void* data)
{
	DEBUG_MSG2("Res [%s]\n", response);
	vector<string>* lines = (vector<string>*)data;
	lines->push_back(response);

	return 0;
}

int CAppDatabaseCfg::Config(void)
{
	int n = 0;

	uint8 mode = static_cast<uint8>(dbType_);
	string server = server_;
	string server2 = server2_;
	string user = user_;
	string password = password_;
	string database = database_;
#if ARM64

	CFormRect rectInpBtn;
	CFormButton btnOk;

	while(1) {
		FORM_INIT(MySQL, EventConfigMySQLShow, NULL, NULL, NULL, /*nFormFlgShowHelp |*/ nFormFlgAutoPresentPopup | nFormFlgShowPopupTabKeypad);

		SetupInputFormToUseFontSet(formMySQL, rectInpBtn, 0.40, 1.2);
		CFormAdvanceY advY;
		advY.SetBasedOnFont(formFontSet.GetFont(fontIndexPrompt), 1.4);

		FORM_ADD_INPUT2(MySQL, Mode, rectInpBtn, rectKeypad, "Mode: ", 14, 0, 2, EventDatabaseModeChg, mode, 	FORM_UINT8_SEL | FORM_FLAG_POPUP_LEFT_PROMPT, 	"SQLite|MySQL|SQL Server", NULL, DB_CFG_MODE);
		rectInpBtn += advY;
		FORM_ADD_INPUT2(MySQL, Server, rectInpBtn, rectKeypad, "Server: ", 40, 0, 0, NULL, server, 	FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, 	NULL, NULL, DB_CFG_SERVER);
		rectInpBtn += advY;
		FORM_ADD_INPUT2(MySQL, Server2, rectInpBtn, rectKeypad, " ", 40, 0, 0, NULL, server2, 	FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, 	NULL, NULL, DB_CFG_SERVER2);
		rectInpBtn += advY;
		FORM_ADD_INPUT2(MySQL, User, rectInpBtn, rectKeypad, "User: ", 40, 0, 0, NULL, user, 	FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, 	NULL, NULL, DB_CFG_USER);
		rectInpBtn += advY;
		FORM_ADD_INPUT2(MySQL, Password, rectInpBtn, rectKeypad, "Password: ", 40, 0, 0, NULL, password, 	FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, 	NULL, NULL, DB_CFG_PASSWORD);
		rectInpBtn += advY;
		FORM_ADD_INPUT2(MySQL, Database, rectInpBtn, rectKeypad, "Database: ", 40, 0, 0, NULL, database, 	FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, 	NULL, NULL, DB_CFG_DATABASE);

		formMySQL.LeftAlignPromptInputs(inpMode, inpDatabase);

		AddFormOkButton(formMySQL, btnOk);

		formMySQL.SetUserStruct(this);

		FORM_SHOW(MySQL);
		UpdateConfigForm(&formMySQL);

		n = FORM_RUN(MySQL);
		FORM_HIDE(MySQL);

		if(n == FORM_RESULT_ESC || static_cast<AppDbType>(mode) == appDataSQLite) {
			break;
		}
		if(password.length() < 3) {
			DrawMessageBox("Password too short", 2);
		} else {
			break;
		}

	}

	if (n != FORM_RESULT_ESC) {

		if(static_cast<AppDbType>(mode) != dbType_ || server_ != server || server2_ != server2 || user_ != user || password_ != password || database_ != database) {
			if (DrawConfirmBox("Are you sure you want to change database settings?", LANG(STR_YES), LANG(STR_NO))) {
				dbType_ = static_cast<AppDbType>(mode);
				server_ = server;
				server2_ = server2;
				user_ = user;
				password_ = password;
				database_ = database;

				chg_ = true;

				WriteJSON();

				if(dbType_ == appDataMySQL) {
					if(server_ == "127.0.0.1" || server_ == "localhost") {

						bool checkForDatabase = false;
						if(IsServiceActive("mysqld") == false) {
							if (DrawConfirmBox("Enable local MySQL Server?", LANG(STR_YES), LANG(STR_NO))) {
								SetService("mysqld", true);
								SleepMilliseconds(1000);
								DoShellCmd("sudo enablemysql");
								checkForDatabase = true;
							}

						} else {
							checkForDatabase = true;
						}

						if(checkForDatabase) {
							// Check if database exists
							vector<string> lines;
							bool found = false;
							const char* cmd = "sudo mysql -e \"show databases;\"";
							DoShellCmd(cmd, show_db_callback, &lines);
							for(auto& line : lines) {
								DEBUG_MSG("response [%s]\n", line.c_str());
								if(line == database_) {
									DEBUG_MSG("%s found\n", database_.c_str());
									found = true;
								}
							}
							if(found == false) {
								if (DrawConfirmBox("Create database?", LANG(STR_YES), LANG(STR_NO))) {
									string cmd = "sudo createdb " + database_;
									DoShellCmd(cmd.c_str());
									SleepMilliseconds(200);
									cmd = "sudo createdbuser " + database_ + " " + user_ + " \"" + password_ + "\"";
									DoShellCmd(cmd.c_str());
								}
							}
						}
					}
				}


				DrawMessageBox("Restart app to apply database changes", 4);
			}
		}
	}

#else

#endif

	return n;
}

EVENT(ConfigDBFirstTimeShow)
{
	ClearScreenAndShowTitle(pForm, "Database first-time configuration");

	CFormRect rect;
	CFormAdvanceY advY;

	rect.SetTopAndHeightBasedOnFont(pForm->GetFontSet()->GetFont(fontIndexSmallPrompt), 2.4, 1.0);
	rect.SetLeftAndWidthBasedOnDspArea(pForm->GetDspArea(), 0.03, 0.92);

	advY.SetBasedOnFont(pForm->GetFontSet()->GetFont(fontIndexSmallPrompt), 1.0);

	const char* lines[] = { "Select \"SQLite\" for legacy 825 style database.", "", "Select \"Local MySQL\" to be able to view reports of the", "data on this indicator's web page.",
		"", "Select \"Advanced\" for a custom configuration such as using", "a MySQL database on another server."
	};
	int n;
	SetCurColor(COLOR_REQUEST);

	for(n = 0; n < ARRAY_ELEMS(lines); n++) {
		if(lines[n][0] != '\0') {
			pForm->GetFontSet()->GetFont(fontIndexSmallPrompt).DisplayTextCairo(rect, lines[n]);
		}
		rect += advY;
	}

	return 0;
}

enum { FIRSTTIME_DB_SQLITE = 1, FIRSTTIME_DB_LOCAL_MYSQL, FIRSTTIME_DB_ADVANCED };

int CAppDatabaseCfg::FirstTimePrompt(void)
{
	CFormRect rect;

	FORM_INIT(FirstTime, EventConfigDBFirstTimeShow, NULL, NULL, NULL, 0);

	SetupMenuFormToUseFontSet(formFirstTime, rect, MENU_BTN_WIDE_WIDTH);

	rect.SetTopBasedOnFont(formFontSet.GetFont(fontIndexPrompt), 9.0);

	FORM_ADD_BUTTON2(FirstTime, SQLite, rect, "SQLite", 'S', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_SQLITE);
	rect += buttonAdvanceY;
	FORM_ADD_BUTTON2(FirstTime, MySQL,	rect, "Local MySQL - Allows web page reporting", 	'M', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_LOCAL_MYSQL);
	rect += buttonAdvanceY;
	FORM_ADD_BUTTON2(FirstTime, Advanced,	rect, "Advanced", 	'M', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_ADVANCED);

	FORM_SHOW(FirstTime);
	int n = FORM_RUN(FirstTime);
	FORM_HIDE(FirstTime);

	if(n == FIRSTTIME_DB_LOCAL_MYSQL) {
		DEBUG_MSG("Create MySQL database\n");
		dbType_ = appDataMySQL;
		server_ = "127.0.0.1";
		user_ = MYSQL_DEFAULT_DBUSER;
		password_ = "81440";
		database_ = MYSQL_DEFAULT_DB;

		chg_ = true;

		WriteJSON();

		if(IsServiceActive("mysqld") == false) {
			SetService("mysqld", true);
			SleepMilliseconds(1000);
			DoShellCmd("sudo enablemysql");
		}

		vector<string> lines;
		bool found = false;
		const char* cmd = "sudo mysql -e \"show databases;\"";
		DoShellCmd(cmd, show_db_callback, &lines);
		for(auto& line : lines) {
			DEBUG_MSG("response [%s]\n", line.c_str());
			if(line == database_) {
				DEBUG_MSG("%s found\n", database_.c_str());
				found = true;
			}
		}
		if(found == false) {
			//if (DrawConfirmBox("Create database?", LANG(STR_YES), LANG(STR_NO))) {
				string cmd = "sudo createdb " + database_;
				DoShellCmd(cmd.c_str());
				SleepMilliseconds(200);
				cmd = "sudo createdbuser " + database_ + " " + user_ + " \"" + password_ + "\"";
				DoShellCmd(cmd.c_str());
			//}
		}

	} else if(n == FIRSTTIME_DB_ADVANCED) {
		Config();
	}
	DEBUG_MSG("Calling WriteJSON [%s]\n", GetJSONFilepath().c_str());
	WriteJSON();

	return n;
}
