/*
 * libusb event abstraction on Microsoft Windows
 *
 * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <config.h>

#include "libusbi.h"
#include "windows_common.h"

int usbi_create_event(usbi_event_t *event)
{
	event->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (event->hEvent == NULL) {
		usbi_err(NULL, "CreateEvent failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_OTHER;
	}

	return 0;
}

void usbi_destroy_event(usbi_event_t *event)
{
	if (!CloseHandle(event->hEvent))
		usbi_warn(NULL, "CloseHandle failed: %s", windows_error_str(0));
}

void usbi_signal_event(usbi_event_t *event)
{
	if (!SetEvent(event->hEvent))
		usbi_warn(NULL, "SetEvent failed: %s", windows_error_str(0));
}

void usbi_clear_event(usbi_event_t *event)
{
	if (!ResetEvent(event->hEvent))
		usbi_warn(NULL, "ResetEvent failed: %s", windows_error_str(0));
}

#ifdef HAVE_OS_TIMER
int usbi_create_timer(usbi_timer_t *timer)
{
	timer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
	if (timer->hTimer == NULL) {
		usbi_warn(NULL, "CreateWaitableTimer failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_OTHER;
	}

	return 0;
}

void usbi_destroy_timer(usbi_timer_t *timer)
{
	if (!CloseHandle(timer->hTimer))
		usbi_warn(NULL, "CloseHandle failed: %s", windows_error_str(0));
}

int usbi_arm_timer(usbi_timer_t *timer, const struct timespec *timeout)
{
	struct timespec systime, remaining;
	FILETIME filetime;
	LARGE_INTEGER dueTime;
	int r;

	/* Transfer timeouts are based on the monotonic clock and the waitable
	 * timers on the system clock. This requires a conversion between the
	 * two, so we calculate the remaining time relative to the monotonic
	 * clock and calculate an absolute system time for the timer expiration.
	 * Note that if the timeout has already passed, the remaining time will
	 * be negative and thus an absolute system time in the past will be set.
	 * This works just as intended because the timer becomes signalled
	 * immediately. */
	r = usbi_clock_gettime(USBI_CLOCK_MONOTONIC, &systime);
	if (r < 0) {
		usbi_err(NULL, "failed to read monotonic clock");
		return LIBUSB_ERROR_OTHER;
	}

	TIMESPEC_SUB(timeout, &systime, &remaining);

	GetSystemTimeAsFileTime(&filetime);
	dueTime.LowPart = filetime.dwLowDateTime;
	dueTime.HighPart = filetime.dwHighDateTime;
	dueTime.QuadPart += (remaining.tv_sec * 10000000LL) + (remaining.tv_nsec / 100LL);

	if (!SetWaitableTimer(timer->hTimer, &dueTime, 0, NULL, NULL, FALSE)) {
		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_OTHER;
	}

	return 0;
}

int usbi_disarm_timer(usbi_timer_t *timer)
{
	LARGE_INTEGER dueTime;

	/* A manual-reset waitable timer will stay in the signalled state until
	 * another call to SetWaitableTimer() is made. It is possible that the
	 * timer has already expired by the time we come in to disarm it, so to
	 * be entirely sure the timer is disarmed and not in the signalled state,
	 * we will set it with an impossibly large expiration and immediately
	 * cancel. */
	dueTime.QuadPart = LLONG_MAX;
	if (!SetWaitableTimer(timer->hTimer, &dueTime, 0, NULL, NULL, FALSE)) {
		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_OTHER;
	}

	if (!CancelWaitableTimer(timer->hTimer)) {
		usbi_warn(NULL, "SetWaitableTimer failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_OTHER;
	}

	return 0;
}
#endif

int usbi_alloc_event_data(struct libusb_context *ctx)
{
	struct usbi_event_source *ievent_source;
	HANDLE *handles;
	size_t i = 0;

	/* Event sources are only added during usbi_io_init(). We should not
	 * be running this function again if the event data has already been
	 * allocated. */
	if (ctx->event_data) {
		usbi_warn(ctx, "program assertion failed - event data already allocated");
		return LIBUSB_ERROR_OTHER;
	}

	ctx->event_data_cnt = 0;
	for_each_event_source(ctx, ievent_source)
		ctx->event_data_cnt++;

	/* We only expect up to two HANDLEs to wait on, one for the internal
	 * signalling event and the other for the timer. */
	if (ctx->event_data_cnt != 1 && ctx->event_data_cnt != 2) {
		usbi_err(ctx, "program assertion failed - expected exactly 1 or 2 HANDLEs");
		return LIBUSB_ERROR_OTHER;
	}

	handles = calloc(ctx->event_data_cnt, sizeof(HANDLE));
	if (!handles)
		return LIBUSB_ERROR_NO_MEM;

	for_each_event_source(ctx, ievent_source) {
		handles[i] = ievent_source->data.os_handle;
		i++;
	}

	ctx->event_data = handles;
	return 0;
}

int usbi_wait_for_events(struct libusb_context *ctx,
	struct usbi_reported_events *reported_events, int timeout_ms)
{
	HANDLE *handles = ctx->event_data;
	DWORD num_handles = (DWORD)ctx->event_data_cnt;
	DWORD result;

	usbi_dbg("WaitForMultipleObjects() for %lu HANDLEs with timeout in %dms", ULONG_CAST(num_handles), timeout_ms);
	result = WaitForMultipleObjects(num_handles, handles, FALSE, (DWORD)timeout_ms);
	usbi_dbg("WaitForMultipleObjects() returned %lu", ULONG_CAST(result));
	if (result == WAIT_TIMEOUT) {
		if (usbi_using_timer(ctx))
			goto done;
		return LIBUSB_ERROR_TIMEOUT;
	} else if (result == WAIT_FAILED) {
		usbi_err(ctx, "WaitForMultipleObjects() failed: %s", windows_error_str(0));
		return LIBUSB_ERROR_IO;
	}

	result -= WAIT_OBJECT_0;

	/* handles[0] is always the internal signalling event */
	if (result == 0)
		reported_events->event_triggered = 1;
	else
		reported_events->event_triggered = 0;

#ifdef HAVE_OS_TIMER
	/* on timer configurations, handles[1] is the timer */
	if (usbi_using_timer(ctx)) {
		/* The WaitForMultipleObjects() function reports the index of
		 * the first object that became signalled. If the internal
		 * signalling event was reported, we need to also check and
		 * report whether the timer is in the signalled state. */
		if (result == 1 || WaitForSingleObject(handles[1], 0) == WAIT_OBJECT_0)
			reported_events->timer_triggered = 1;
		else
			reported_events->timer_triggered = 0;
	} else {
		reported_events->timer_triggered = 0;
	}
#endif

done:
	/* no events are ever reported to the backend */
	reported_events->num_ready = 0;
	return LIBUSB_SUCCESS;
}
