/* GPC (C) 2017-2018 Stephane Charette <stephanecharette@gmail.com>
 * $Id: GPCApp.hpp 2473 2018-03-09 16:48:43Z stephane $
 */

#pragma once

#include "GPC.hpp"


class GPCApplication : public JUCEApplication, public Timer
{
	public:

		enum class EJob
		{
			kInvalid					,
			kInitializeAndLoad			,
			kShowFirstWindow			,
			kShowSummaryWindow			,
			kShowAboutWindow			,
			kShutdown					,
			kNoOp
		};

		GPCApplication						(void);
		virtual ~GPCApplication				(void);

		const String getApplicationName		(void) override	{ return "Gorman Print Control";	}
		const String getApplicationVersion	(void) override	{ return GPC_VERSION;				}
		bool moreThanOneInstanceAllowed		(void) override	{ return true;						}
		void systemRequestedQuit			(void) override { quit();							}

		void initialise(const String& commandLine) override;

		void shutdown() override;

		void anotherInstanceStarted (const String& commandLine) override;

		void unhandledException(const std::exception *e, const String &sourceFilename, int lineNumber) override;

		void run( const EJob job );

		void job_initialize_and_load(void);

		void job_show_about_window(void);

		/// Inherited from Timer.  Used to save configuration to disk after a set interval.
		virtual void timerCallback(void);

		TooltipWindow						tool_tip;

		std::unique_ptr<LookAndFeel_V4>		laf;
		std::unique_ptr<Cfg>				cfg;
		std::unique_ptr<SummaryWnd>			summary_wnd;

		/// Base directory in which all of the Print Control files can be found, including the .JSON file.
		File directory;

		VStr errors;

		MSessions sessions;
};


/** Return a reference to the single running application.  Will throw if the
 * app somehow does not exist, such as early in the startup process, or late
 * in the shutdown sequence.
 */
inline GPCApplication &gpc(void)
{
	GPCApplication *app = dynamic_cast<GPCApplication*>(JUCEApplication::getInstance());
	if (app == nullptr)
	{
		throw Lox::Exception( LOX_WHERE, "failed to find an active application pointer" );
	}

	return *app;
}


inline GPCApplication &run(const GPCApplication::EJob job)
{
	GPCApplication &app( gpc() );

	app.run(job);

	return app;
}


/// Quick and easy access to configuration.  Will throw if the GPC application does not exist.
inline Cfg &cfg(void)
{
	return *gpc().cfg;
}


inline SummaryWnd &summaryWnd(void)
{
	return *gpc().summary_wnd;
}


#if 0
/// Quick and easy access to the JSON object.  Will throw if the GPC application does not exist.
inline Json &json(void)
{
	return gpc().json;
}
#endif


inline std::string to_string(const GPCApplication::EJob job)
{
	switch(job)
	{
		case GPCApplication::EJob::kInvalid:					return "invalid";
		case GPCApplication::EJob::kInitializeAndLoad:			return "initialize and load";
		case GPCApplication::EJob::kShowFirstWindow:			return "show first window";
		case GPCApplication::EJob::kShowSummaryWindow:			return "show summary window";
		case GPCApplication::EJob::kShowAboutWindow:			return "about window";
		case GPCApplication::EJob::kShutdown:					return "shutdown";
		case GPCApplication::EJob::kNoOp:						return "no-op";
	}

	return "?";
}
