#include <CtrlLib/CtrlLib.h>
using namespace Upp;

bool ProcessForeground(){
#ifdef _MULTITHREADED
	DUMP(Thread::IsShutdownThreads());
	return !Thread::IsShutdownThreads();
#else
	Ctrl::ProcessEvents();
	return true; //is it possible to detect application is being closed?
#endif
}

class BackgroundTask{
	typedef BackgroundTask CLASSNAME;
	#ifdef _MULTITHREADED
	Thread t;
	#endif
	bool running;
	void Watch(Callback task);
public:
	void Start(Callback task);
	bool IsRunning()                  {return running;}
	BackgroundTask():running(false){}
	BackgroundTask(Callback task)     {Start(task);}
};

void BackgroundTask::Watch(Callback task){
	running=true;
	task();
	running=false;
}

void BackgroundTask::Start(Callback task){
	#ifdef _MULTITHREADED
	t.Run(THISBACK1(Watch,task));
	#else
	PostCallback(THISBACK1(Watch,task));
	#endif
}

class App:public TopWindow {
	typedef App CLASSNAME;
	BackgroundTask b;
	TimeStop t;
public:
	void DoSomethingSlow(){
		for(int i=0;i<500;i++){
			Sleep(10);
			if(!ProcessForeground())
				return;
		}
	}
	void Check(){
		if(b.IsRunning())
			Title("Doing something slow ("+AsString(t.Elapsed()/1000.0)+" seconds)");
		else
			Title("Finished");
	}
	#ifdef _MULTITHREADED
	virtual void Close(){
		Thread::ShutdownThreads();
		TopWindow::Close();
	}
	#endif
	App(){
		Title("Started");
		t.Reset();
		SetTimeCallback(-250,THISBACK(Check));
		b.Start(THISBACK(DoSomethingSlow));
	}
};

GUI_APP_MAIN{
	App().Sizeable().Run();
}
