#include <functional>
#include <string>
#include <vector>
#include <memory>

#include "animone.h"
#include "animone/a11y/atspi.h"

#include <atspi/atspi.h>

namespace animone::internal::atspi {

/* deleters */
template<typename T>
struct g_object_del {
    void operator()(T* p) const { ::g_object_unref(p); };
};

template<typename T>
using GObjectPtr = std::unique_ptr<T, g_object_del<T>>;

/* ----------------------------------------------------------------- */

// FIXME | atspi_exit()
bool GetWebBrowserInformation(const Result& result, web_browser_proc_t web_browser_proc) {
	GObjectPtr<AtspiAccessible> desktop;
	GObjectPtr<AtspiAccessible> application;

	{
		int err = atspi_init();
		if (err != 0 && err != 1)
			return false;
	}

	// Currently only one desktop is supported, so this is equivalent to doing
	// just atspi_get_desktop(0). However it's nice to futureproof where possible.
	for (gint i = 0; i < atspi_get_desktop_count(); i++) {
		desktop.reset(atspi_get_desktop(i));
		if (!desktop)
			return false;

		for (gint j = 0; j < atspi_accessible_get_child_count(desktop.get(), nullptr); j++) {
			application.reset(atspi_accessible_get_child_at_index(desktop.get(), j, nullptr));
			if (!application)
				return false;

			GError *error = NULL;

			std::uint32_t pid = atspi_accessible_get_process_id(application.get(), &error);
			if (error) {
				::g_error_free(error);
				return false;
			}

			if (pid == result.process.pid)
				goto found; // found it
		}
	}

	// didn't get anything... lol
	return false;

found:
	// found a matching application

	gchar *title = atspi_accessible_get_name(application.get(), NULL);
	if (title) {
		web_browser_proc({WebBrowserInformationType::Title, title});
		::g_free(title);
	}

	// TODO need to find address and tab? idk

	return true;
}

}
