#include "animone.h"
#include "animone/fd.h"
#include "animone/strategies.h"
#include "animone/types.h"
#include "animone/util.h"
#include "animone/win.h"

#include <set>
#include <string>
#include <vector>

#include <iostream>

namespace animone {

namespace internal {

static bool IsExecutableInList(const Player& player, const Process& proc) {
	for (const auto& [platform, comms] : player.executables)
		for (const auto& comm : comms)
			if (platform == proc.platform && util::CheckPattern(comm, proc.comm))
				return true;

	return false;
}

static bool IsWindowInList(const Player& player, const Window& window) {
	for (const auto& [platform, class_names] : player.windows)
		for (const auto& class_name : class_names)
			if (platform == window.platform && util::CheckPattern(class_name, window.class_name))
				return true;

	return false;
}

static bool PlayerHasStrategy(const Player& player, const Strategy& strategy) {
	for (const auto& pstrategy : player.strategies)
		if (pstrategy == strategy)
			return true;

	return false;
}

} // namespace internal

bool GetResults(const std::vector<Player>& players, std::vector<Result>& results) {
	auto window_proc = [&](const Process& process, const Window& window) -> bool {
		for (const auto& player : players)
			if (internal::IsWindowInList(player, window) && internal::IsExecutableInList(player, process))
				results.push_back({player, process, window, {}});

		return true;
	};

	if (internal::EnumerateWindows(window_proc) && internal::ApplyStrategies(results))
		return true;

	/* fallback, enumerate over open processes instead */
	auto process_proc = [&](const Process& process) -> bool {
		for (const auto& player : players)
			if (internal::IsExecutableInList(player, process))
				results.push_back({player, process, {}, {}});

		return true;
	};

	if (internal::EnumerateOpenProcesses(process_proc) && internal::ApplyStrategies(results))
		return true;

	return false;
}

} // namespace animone
