/* GMM (C) 2018 Stephane Charette <stephanecharette@gmail.com>
 * $Id: GMMWnd.cpp 2687 2018-12-06 21:15:40Z stephane $
 */

#include "GMM.hpp"
#include "src-img.hpp"


GMMWnd::GMMWnd(void) :
	DocumentWindow(
		"GMM v"  + String(GMM_VERSION),
		Desktop::getInstance().getDefaultLookAndFeel().findColour(ResizableWindow::backgroundColourId),
		DocumentWindow::TitleBarButtons::minimiseButton	+
		DocumentWindow::TitleBarButtons::maximiseButton	+
		(cfg().get_bool("allow_user_to_close") ? DocumentWindow::TitleBarButtons::closeButton : 0)),
	child_opc_process_handle(INVALID_HANDLE_VALUE)
{
	// Even though we attempt to set the initial colour of the tab here, the notebook has also been modified
	// to edit the colour of the active/inactive tabs.  For more details, see Notebook::currentTabChanged().
	const Colour bgColour = gmm().laf->getCurrentColourScheme().getUIColour(LookAndFeel_V4::ColourScheme::windowBackground);

	// start the OPC C# application

//	const std::string directory_name			= "C:\\Program Files\\gmm\\bin";
	const std::string directory_name			= File::getSpecialLocation(File::currentApplicationFile).getParentDirectory().getFullPathName().toStdString();
	const std::string configuration_name		= cfg().getFile().getFullPathName().toStdString();
	const std::string opc_console_executable	= cfg().get_str("opc_console_application");
	const std::string commandline				= opc_console_executable + " \"" + configuration_name + "\"";

	// argument to CreateProcess() needs non-const char, so make a copy of it in a temporary buffer
	std::vector<char> tmp;
	tmp.resize(commandline.size() + 1, '\0');
	strcpy(tmp.data(), commandline.c_str());

	LOG_MSG("starting OPC console: \"" << commandline << "\"" );

	PROCESS_INFORMATION pi = {0};
	STARTUPINFOA si = {0};
	si.cb = sizeof(si);
	si.lpTitle = "GMM OPC Console";
	si.dwFillAttribute = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
	si.dwFlags = STARTF_USEFILLATTRIBUTE;

	const BOOL result = CreateProcessA(
		nullptr,
		tmp.data(),
		nullptr,
		nullptr,
		FALSE,
		cfg().get_bool("opc_show_console_window") ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW,
		nullptr,
		directory_name.c_str(),
		&si,
		&pi);

	if (result == FALSE)
	{
		warnings_and_errors.push_back("Failed to start the OPC console application.");
		Lox::Exception e(LOX_WHERE, "failed to create child process for OPC console window");
		LOG_MSG(e.to_string());
	}
	else
	{
		child_opc_process_handle = pi.hProcess;
		CloseHandle(pi.hThread);
	}

	// create a new tab for every device
	for (const auto & prefix : gmm().prefixes)
	{
		const std::string name = cfg().get_str(prefix + "_name", prefix);
		notebook.addTab(name, bgColour, new TabCanvas(prefix), true);
	}

	setContentNonOwned( &notebook, false );

	centreWithSize			( 640, 480		);
	setUsingNativeTitleBar	( true			);
	setResizable			( true, true	);
	setDropShadowEnabled	( true			);

	setIcon(GormanLogo());
	ComponentPeer *peer = getPeer();
	if (peer)
	{
		peer->setIcon(GormanLogo());
	}

	if (cfg().containsKey("GMMWnd"))
	{
		restoreWindowStateFromString( cfg().getValue("GMMWnd") );
	}

	setVisible(true);

	startTimer(1000); // in milliseconds

	return;
}


GMMWnd::~GMMWnd(void)
{
	stopTimer();

	cfg().setValue("GMMWnd", getWindowStateAsString());

	if (child_opc_process_handle != INVALID_HANDLE_VALUE)
	{
		LOG_MSG("terminating OPC child process");
		TerminateProcess(child_opc_process_handle, 0);
		CloseHandle(child_opc_process_handle);
	}

	return;
}


void GMMWnd::closeButtonPressed(void)
{
	if (cfg().get_bool("allow_user_to_close"))
	{
		run(GMMApplication::EJob::kShutdown);
	}

	return;
}


bool GMMWnd::keyPressed(const KeyPress &key)
{
	const ModifierKeys modifiers = key.getModifiers();
	if (key.isKeyCode(KeyPress::F1Key))
	{
		run(GMMApplication::EJob::kShowAboutWindow);
		return true; // true == consume the keystroke
	}
	else if (key.isKeyCode(KeyPress::F2Key) && modifiers.isShiftDown())
	{
		File f = cfg().getFile();
		f.revealToUser();
		return true; // true == consume the keystroke
	}
	else if (key.isKeyCode(KeyPress::F4Key) && modifiers.isShiftDown())
	{
		File f( get_log_filename() );
		f.startAsProcess();
		return true; // true == consume the keystroke
	}

	return false; // false == keystroke not handled
}


void GMMWnd::timerCallback(void)
{
	const auto result = WaitForSingleObject(child_opc_process_handle, 0);

	if (result == WAIT_OBJECT_0 || child_opc_process_handle == INVALID_HANDLE_VALUE)
	{
		// something has gone wrong -- OPC isn't running!?
		warnings_and_errors.push_back("OPC Console has failed.");
		stopTimer();
	}
	else
	{
		auto f = File::getSpecialLocation(File::tempDirectory).getChildFile("gmm_opc_output.txt");
		if (f.existsAsFile())
		{
			std::ifstream ifs(f.getFullPathName().toStdString());
		}
	}

	return;
}
