#include <stdbool.h>
#include <stdint.h>

#include "listeners.h"

#include "head.h"
#include "info.h"
#include "log.h"
#include "mode.h"
#include "wlr-output-management-unstable-v1.h"

// Mode data

static void size(void *data,
		struct zwlr_output_mode_v1 *zwlr_output_mode_v1,
		int32_t width,
		int32_t height) {
	struct Mode *mode = data;

	mode->width = width;
	mode->height = height;
}

static void refresh(void *data,
		struct zwlr_output_mode_v1 *zwlr_output_mode_v1,
		int32_t refresh) {
	struct Mode *mode = data;

	mode->refresh_mhz = refresh;
}

static void preferred(void *data,
		struct zwlr_output_mode_v1 *zwlr_output_mode_v1) {
	struct Mode *mode = data;

	// some heads may advertise multiple preferred modes; ignore subsequent
	if (mode->head) {
		struct Mode *mode_preferred;
		if ((mode_preferred = head_preferred_mode(mode->head))) {

			static char mode_preferred_buf[2048];
			info_mode_string(mode_preferred, mode_preferred_buf, sizeof(mode_preferred_buf));

			static char mode_buf[2048];
			info_mode_string(mode, mode_buf, sizeof(mode_buf));

			if (mode_preferred->head && mode_preferred->head->name) {
				log_info("\n%s: multiple preferred modes advertised: using initial %s, ignoring %s", mode_preferred->head->name, mode_preferred_buf, mode_buf);
			} else {
				log_info("\n???: multiple preferred modes advertised: using initial %s, ignoring %s", mode_preferred_buf, mode_buf);
			}

			return;
		}
	}

	mode->preferred = true;
}

static void finished(void *data,
		struct zwlr_output_mode_v1 *zwlr_output_mode_v1) {
	struct Mode *mode = data;

	head_release_mode(mode->head, mode);
	mode_free(mode);

	zwlr_output_mode_v1_destroy(zwlr_output_mode_v1);
}

static const struct zwlr_output_mode_v1_listener listener = {
	.size = size,
	.refresh = refresh,
	.preferred = preferred,
	.finished = finished,
};

const struct zwlr_output_mode_v1_listener *zwlr_output_mode_listener(void) {
	return &listener;
}

