#pragma once

#include "app.h"

extern HWND ghWnd;

// per-frame observer called once per RunMissions frame, after the
// foreground pass (the single-player local-console marshal uses this)
extern void (*gPerFrameHook)();

// True when an in-process console marshals the launch: suppresses the
// no-console self-run in CheckLoadMessageHandler so a hosted network
// race stages at WaitingForLaunch until every pod is ready. Plain
// single player leaves it False and auto-runs exactly as always.
extern Logical gConsoleMarshalsLaunch;

// True for lobby-member races: losing the console mid-mission ends the
// mission (the owner left - without a console the timer counts up
// forever). Arcade -net pods leave it False and re-listen for their
// console to return, exactly as always.
extern Logical gConsoleLossEndsMission;

//
// The console's own countdown, when there is a console to ask.
//
// A mission ends when the console says so, but secondsRemainingInGame was
// computed here from the engine clock and its own idea of when the race
// started - a different clock, from a different epoch, than the one that
// actually fires the buzzer. The two agree to within a frame or so, which
// is why nobody noticed, but they are not the same number: the cockpit
// clock could read 0:00 with the race still running, and the camera
// directors' "last 30 seconds" behaviour switched on the engine's reading
// rather than on the real remaining time.
//
// Set by the console when it is marshalling; NULL restores the engine's
// own reckoning, which is what the arcade -net pods, lobby members and
// mission review all use (none of them run a console locally, and their
// clock is anchored by the console's RunMission arriving anyway).
//
// Returns False when it has no answer yet - the window between the
// application reaching RunningMission and the console noticing.
//
extern Logical (*gMissionClockHook)(Scalar *seconds_remaining);

class ApplicationManager : public Node
{
public:
	ApplicationManager(HINSTANCE hInstance, HWND hWnd, Scalar frame_rate);
	~ApplicationManager();

	void StartApplication(Application *new_app);

	void RunMissions();

	Scalar GetFrameRate()
	{
		Check(this);
		return frameRate;
	}

	HINSTANCE	GetHInstance()	{ return mHInstance; }
	HWND		GetHWnd()		{ return ghWnd; }

	static ApplicationManager* GetCurrentManager()	{ return CurrentAppManager; }

protected:
	static ApplicationManager* CurrentAppManager;

	Scalar					frameDuration, frameRate;
	SChainOf<Application*>	runningApplications;
	HINSTANCE				mHInstance;
};
