/* We actually DON'T need Objective-C for most of this file.
 * GetWindowTitle() is the only function that really needs it.
 * (and even then, we can use the C bindings for it...)
 *
 * However, being able to use the Foundation classes makes things
 * so, so, so much easier, and so I've decided to make this file
 * in Objective-C++.
*/
#include "animia/win/quartz.h"
#include "animia.h"

#include <objc/runtime.h>
#include <objc/message.h>

#include <CoreFoundation/CoreFoundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <Carbon/Carbon.h>

namespace animia::internal::quartz {

static bool GetWindowTitle(unsigned int wid, std::string& result) {
	// id app = [NSApplication sharedApplication];
	id app = cls_msg(cls("NSApplication"), sel("sharedApplication"));

	// id window = [app windowWithWindowNumber: wid];
	id window = msg(app, sel("windowWithWindowNumber:"), wid);

	// return [[window title] UTF8String];
	return StringFromCFString(reinterpret_cast<CFStringRef>(msg(window, "title")), result);
}

bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) {
	if (!window_proc)
		return false;

	CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
	if (!windows)
		return false;

	CFIndex i = 0; count = CFArrayGetCount(windows);
	for (; i < count; i++) {
		CFDictionaryRef window = CFArrayGetValueAtIndex(windows, i);
		if (!window)
			continue;

		Process proc;
		{
			{
				CFNumber num;
				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerPID", &num);
				osx::util::GetCFNumber(num, proc.pid);
			}
			{
				CFStringRef str;
				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerName", &str);
				osx::util::StringFromCFString(str, proc.name);
			}
			if (proc.name.empty())
				osx::util::GetProcessName(proc.pid, proc.name);
		}

		Window win;
		{
			{
				CFNumber num;
				CFDictionaryGetValueIfPresent(window, "kCGWindowNumber", &num);
				osx::util::GetCFNumber(num, win.id);
			}
			{
				CFStringRef str;
				CFDictionaryGetValueIfPresent(window, "kCGWindowName", &str);
				osx::util::GetCFNumber(str, win.class_name);
			}
			GetWindowTitle(win.id, win.text);
		}

		if (!window_proc(proc, win))
			return false;
	}

	return true;
}

} // namespace animia::win::detail
