/*
 * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>

#include "wayland-client.h"
#include "wayland-server.h"
#include "test-runner.h"

/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
static const char *
require_xdg_runtime_dir(void)
{
	char *val = getenv("XDG_RUNTIME_DIR");
	assert(val && "set $XDG_RUNTIME_DIR to run this test");

	return val;
}

struct compositor {
	struct wl_display *display;
	struct wl_listener listener;
	struct wl_client *client;
};

static void
client_created(struct wl_listener *listener, void *data)
{
	struct compositor *c = wl_container_of(listener, c, listener);
	c->client = data;
}

static void
check_client_list(struct compositor *compositor)
{
	struct wl_list *client_list;
	struct wl_client *client, *client_it;
	int num_clients = 0;

	client_list = wl_display_get_client_list(compositor->display);
	wl_client_for_each(client_it, client_list) {
		num_clients++;
		client = client_it;
	}
	assert(num_clients == 1);
	/* 'client_it' is not valid here, so we took a copy of the client in the loop.
	 * We could also do this assert in the loop directly, but in case it fails it is
	 * easier to understand the problem when we know that the previous assert passed,
	 * so that there is only one client but the wrong one. */
	assert(compositor->client == client);
}

static const char *
setup_compositor(struct compositor *compositor)
{
	const char *socket;

	require_xdg_runtime_dir();

	compositor->display = wl_display_create();
	socket = wl_display_add_socket_auto(compositor->display);

	compositor->listener.notify = client_created;
	wl_display_add_client_created_listener(compositor->display, &compositor->listener);

	return socket;
}

static void
cleanup_compositor(struct compositor *compositor)
{
	wl_client_destroy(compositor->client);
	wl_display_destroy(compositor->display);
}

TEST(new_client_connect)
{
	const char *socket;
	struct compositor compositor = { 0 };
	struct {
		struct wl_display *display;
	} client;

	socket = setup_compositor(&compositor);

	client.display = wl_display_connect(socket);

	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);

	assert(compositor.client != NULL);

	check_client_list(&compositor);



	wl_display_disconnect(client.display);
	cleanup_compositor(&compositor);
}

struct resource_listener {
	struct wl_listener listener;
	int count;
};

static void
resource_created(struct wl_listener *listener, void *data)
{
	struct resource_listener *l;
	l = wl_container_of(listener, l, listener);
	l->count++;
}

TEST(new_resource)
{
	const char *socket;
	struct compositor compositor = { 0 };
	struct {
		struct wl_display *display;
		struct wl_callback *cb;
	} client;
	struct resource_listener resource_listener;

	socket = setup_compositor(&compositor);
	client.display = wl_display_connect(socket);
	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);

	resource_listener.count = 0;
	resource_listener.listener.notify = resource_created;
	wl_client_add_resource_created_listener(compositor.client,
						&resource_listener.listener);

	client.cb = wl_display_sync(client.display);
	wl_display_flush(client.display);
	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);

	assert(resource_listener.count == 1);

	wl_callback_destroy(client.cb);
	wl_display_disconnect(client.display);
	cleanup_compositor(&compositor);

	/* This is defined to be safe also after client destruction */
	wl_list_remove(&resource_listener.listener.link);
}
