/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission to use, copy, modify, distribute, and sell this software and
 * its documentation for any purpose is hereby granted without fee, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the copyright holders not be used in
 * advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  The copyright holders make
 * no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <X11/Xcursor/Xcursor.h>

#include "xwayland.h"

#include "cairo-util.h"
#include "compositor.h"
#include "hash.h"

static void
weston_dnd_start(struct weston_wm *wm, xcb_window_t owner)
{
	uint32_t values[1], version = 4;

	wm->dnd_window = xcb_generate_id(wm->conn);
	values[0] =
		XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
		XCB_EVENT_MASK_PROPERTY_CHANGE;

	xcb_create_window(wm->conn,
			  XCB_COPY_FROM_PARENT,
			  wm->dnd_window,
			  wm->screen->root,
			  0, 0,
			  8192, 8192,
			  0,
			  XCB_WINDOW_CLASS_INPUT_ONLY,
			  wm->screen->root_visual,
			  XCB_CW_EVENT_MASK, values);
	xcb_change_property(wm->conn,
			    XCB_PROP_MODE_REPLACE,
			    wm->dnd_window,
			    wm->atom.xdnd_aware,
			    XCB_ATOM_ATOM,
			    32, /* format */
			    1, &version);

	xcb_map_window(wm->conn, wm->dnd_window);
	wm->dnd_owner = owner;
}

static void
weston_dnd_stop(struct weston_wm *wm)
{
	xcb_destroy_window(wm->conn, wm->dnd_window);
	wm->dnd_window = XCB_WINDOW_NONE;
}

struct dnd_data_source {
	struct weston_data_source base;
	struct weston_wm *wm;
	int version;
	uint32_t window;
};

static void
data_source_accept(struct weston_data_source *base,
		   uint32_t time, const char *mime_type)
{
	struct dnd_data_source *source = (struct dnd_data_source *) base;
	xcb_client_message_event_t client_message;
	struct weston_wm *wm = source->wm;

	weston_log("got accept, mime-type %s\n", mime_type);

	/* FIXME: If we rewrote UTF8_STRING to
	 * text/plain;charset=utf-8 and the source doesn't support the
	 * mime-type, we'll have to rewrite the mime-type back to
	 * UTF8_STRING here. */

	client_message.response_type = XCB_CLIENT_MESSAGE;
	client_message.format = 32;
	client_message.window = wm->dnd_window;
	client_message.type = wm->atom.xdnd_status;
	client_message.data.data32[0] = wm->dnd_window;
	client_message.data.data32[1] = 2;
	if (mime_type)
		client_message.data.data32[1] |= 1;
	client_message.data.data32[2] = 0;
	client_message.data.data32[3] = 0;
	client_message.data.data32[4] = wm->atom.xdnd_action_copy;

	xcb_send_event(wm->conn, 0, wm->dnd_owner,
			       XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
			       (char *) &client_message);
}

static void
data_source_send(struct weston_data_source *base,
		 const char *mime_type, int32_t fd)
{
	struct dnd_data_source *source = (struct dnd_data_source *) base;
	struct weston_wm *wm = source->wm;

	weston_log("got send, %s\n", mime_type);

	/* Get data for the utf8_string target */
	xcb_convert_selection(wm->conn,
			      wm->selection_window,
			      wm->atom.xdnd_selection,
			      wm->atom.utf8_string,
			      wm->atom.wl_selection,
			      XCB_TIME_CURRENT_TIME);

	xcb_flush(wm->conn);

	fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK);
	wm->data_source_fd = fd;
}

static void
data_source_cancel(struct weston_data_source *source)
{
	weston_log("got cancel\n");
}

static void
handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message)
{
	struct dnd_data_source *source;
	struct weston_seat *seat = weston_wm_pick_seat(wm);
	char **p;
	const char *name;
	uint32_t *types;
	int i, length, has_text;
	xcb_get_property_cookie_t cookie;
	xcb_get_property_reply_t *reply;

	source = malloc(sizeof *source);
	if (source == NULL)
		return;

	wl_signal_init(&source->base.destroy_signal);
	source->base.accept = data_source_accept;
	source->base.send = data_source_send;
	source->base.cancel = data_source_cancel;
	source->wm = wm;
	source->window = client_message->data.data32[0];
	source->version = client_message->data.data32[1] >> 24;

	if (client_message->data.data32[1] & 1) {
		cookie = xcb_get_property(wm->conn,
					  0, /* delete */
					  source->window,
					  wm->atom.xdnd_type_list,
					  XCB_ATOM_ANY, 0, 2048);
		reply = xcb_get_property_reply(wm->conn, cookie, NULL);
		types = xcb_get_property_value(reply);
		length = reply->value_len;
	} else {
		reply = NULL;
		types = &client_message->data.data32[2];
		length = 3;
	}

	wl_array_init(&source->base.mime_types);
	has_text = 0;
	for (i = 0; i < length; i++) {
		if (types[i] == XCB_ATOM_NONE)
			continue;

		name = get_atom_name(wm->conn, types[i]);
		if (types[i] == wm->atom.utf8_string ||
		    types[i] == wm->atom.text_plain_utf8 ||
		    types[i] == wm->atom.text_plain) {
			if (has_text)
				continue;

			has_text = 1;
			p = wl_array_add(&source->base.mime_types, sizeof *p);
			if (p)
				*p = strdup("text/plain;charset=utf-8");
		} else if (strchr(name, '/')) {
			p = wl_array_add(&source->base.mime_types, sizeof *p);
			if (p)
				*p = strdup(name);
		}
	}

	free(reply);
	weston_pointer_start_drag(seat->pointer, &source->base, NULL, NULL);
}

int
weston_wm_handle_dnd_event(struct weston_wm *wm,
			   xcb_generic_event_t *event)
{
	xcb_xfixes_selection_notify_event_t *xfixes_selection_notify =
		(xcb_xfixes_selection_notify_event_t *) event;
	xcb_client_message_event_t *client_message =
		(xcb_client_message_event_t *) event;

	switch (event->response_type - wm->xfixes->first_event) {
	case XCB_XFIXES_SELECTION_NOTIFY:
		if (xfixes_selection_notify->selection != wm->atom.xdnd_selection)
			return 0;

		weston_log("XdndSelection owner: %d!\n",
			   xfixes_selection_notify->owner);

		if (xfixes_selection_notify->owner != XCB_WINDOW_NONE)
			weston_dnd_start(wm, xfixes_selection_notify->owner);
		else
			weston_dnd_stop(wm);

		return 1;
	}

	switch (EVENT_TYPE(event)) {
	case XCB_CLIENT_MESSAGE:
		if (client_message->type == wm->atom.xdnd_enter) {
			handle_enter(wm, client_message);
			return 1;
		} else if (client_message->type == wm->atom.xdnd_leave) {
			weston_log("got leave!\n");
			return 1;
		} else if (client_message->type == wm->atom.xdnd_drop) {
			weston_log("got drop!\n");
			return 1;
		} else if (client_message->type == wm->atom.xdnd_drop) {
			weston_log("got enter!\n");
			return 1;
		}
		return 0;
	}

	return 0;
}

void
weston_wm_dnd_init(struct weston_wm *wm)
{
	uint32_t mask;

	mask =
		XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
		XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
		XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
	xcb_xfixes_select_selection_input(wm->conn, wm->selection_window,
					  wm->atom.xdnd_selection, mask);
}
