/*
 * poll_windows: poll compatibility wrapper for Windows
 * Copyright © 2017 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
 *
 */

/*
 * poll() and pipe() Windows compatibility layer for libusb 1.0
 *
 * The way this layer works is by using OVERLAPPED with async I/O transfers, as
 * OVERLAPPED have an associated event which is flagged for I/O completion.
 *
 * For USB pollable async I/O, you would typically:
 * - obtain a Windows HANDLE to a file or device that has been opened in
 *   OVERLAPPED mode
 * - call usbi_create_fd with this handle to obtain a custom fd.
 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
 *
 * The pipe pollable synchronous I/O works using the overlapped event associated
 * with a fake pipe. The read/write functions are only meant to be used in that
 * context.
 */
#include <config.h>

#include <assert.h>
#include <errno.h>
#include <stdlib.h>

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

// public fd data
const struct winfd INVALID_WINFD = { -1, NULL };

// private data
struct file_descriptor {
	enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
	OVERLAPPED overlapped;
	int refcount;
};

static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;

static struct file_descriptor **fd_table;
static size_t fd_count;
static size_t fd_size;
#define INC_FDS_EACH 256

static void usbi_dec_fd_table()
{
	fd_count--;
	if (fd_count == 0) {
		free(fd_table);
		fd_table = NULL;
	}
}

static void smart_realloc_fd_table_space(int inc)
{
	if (fd_count + inc > fd_size) {
		struct file_descriptor **p = (struct file_descriptor *)realloc(fd_table, (fd_size + INC_FDS_EACH) * sizeof(struct file_descriptor *));
		if (p != NULL) {
			memset(p + fd_size, 0, INC_FDS_EACH * sizeof(struct file_descriptor *));
			fd_size += INC_FDS_EACH;
			fd_table = p;
		}
	}
}

static struct file_descriptor *create_fd(enum fd_type type)
{
	struct file_descriptor *fd = calloc(1, sizeof(*fd));
	if (fd == NULL)
		return NULL;
	fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (fd->overlapped.hEvent == NULL) {
		free(fd);
		return NULL;
	}
	fd->type = type;
	fd->refcount = 1;
	return fd;
}

static void free_fd(struct file_descriptor *fd)
{
	CloseHandle(fd->overlapped.hEvent);
	free(fd);
}

/*
 * Create both an fd and an OVERLAPPED, so that it can be used with our
 * polling function
 * The handle MUST support overlapped transfers (usually requires CreateFile
 * with FILE_FLAG_OVERLAPPED)
 * Return a pollable file descriptor struct, or INVALID_WINFD on error
 *
 * Note that the fd returned by this function is a per-transfer fd, rather
 * than a per-session fd and cannot be used for anything else but our
 * custom functions.
 * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
 * read and one for write. Using a single R/W fd is unsupported and will
 * produce unexpected results
 */
struct winfd usbi_create_fd(void)
{
	struct file_descriptor *fd;
	struct winfd wfd;

	fd = create_fd(FD_TYPE_TRANSFER);
	if (fd == NULL)
		return INVALID_WINFD;

	usbi_mutex_static_lock(&fd_table_lock);

	smart_realloc_fd_table_space(1);

	for (wfd.fd = 0; wfd.fd < fd_size; wfd.fd++) {
		if (fd_table[wfd.fd] != NULL)
			continue;
		fd_table[wfd.fd] = fd;
		fd_count++;
		break;
	}
	usbi_mutex_static_unlock(&fd_table_lock);

	if (wfd.fd == fd_size) {
		free_fd(fd);
		return INVALID_WINFD;
	}

	wfd.overlapped = &fd->overlapped;

	return wfd;
}

void usbi_inc_fds_ref(struct pollfd *fds, unsigned int nfds)
{
	int n;
	usbi_mutex_static_lock(&fd_table_lock);
	for (n = 0; n < nfds; ++n) {
		fd_table[fds[n].fd]->refcount++;
	}
	usbi_mutex_static_unlock(&fd_table_lock);
}

void usbi_dec_fds_ref(struct pollfd *fds, unsigned int nfds)
{
	int n;
	struct file_descriptor *fd;

	usbi_mutex_static_lock(&fd_table_lock);
	for (n = 0; n < nfds; ++n) {
		fd = fd_table[fds[n].fd];
		fd->refcount--;
		//FD_TYPE_PIPE map fd to two _fd
		if (fd->refcount == 0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
		{
			if (fd->type == FD_TYPE_PIPE) {
				// InternalHigh is our reference count
				fd->overlapped.InternalHigh--;
				if (fd->overlapped.InternalHigh == 0)
					free_fd(fd);
			}
			else {
				free_fd(fd);
			}
			fd_table[fds[n].fd] = NULL;
			usbi_dec_fd_table();
		}
	}
	usbi_mutex_static_unlock(&fd_table_lock);
}


static int check_pollfds(struct pollfd *fds, unsigned int nfds,
	HANDLE *wait_handles, DWORD *nb_wait_handles)
{
	struct file_descriptor *fd;
	unsigned int n;
	int nready = 0;

	usbi_mutex_static_lock(&fd_table_lock);

	for (n = 0; n < nfds; ++n) {
		fds[n].revents = 0;

		// Keep it simple - only allow either POLLIN *or* POLLOUT
		assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT));
		if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) {
			fds[n].revents = POLLNVAL;
			nready++;
			continue;
		}

		if ((fds[n].fd >= 0) && (fds[n].fd < fd_size))
			fd = fd_table[fds[n].fd];
		else
			fd = NULL;

		assert(fd != NULL);
		if (fd == NULL) {
			fds[n].revents = POLLNVAL;
			nready++;
			continue;
		}

		if (HasOverlappedIoCompleted(&fd->overlapped)
				&& (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
			fds[n].revents = fds[n].events;
			nready++;
		} else if (wait_handles != NULL) {
			if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) {
				usbi_warn(NULL, "too many HANDLEs to wait on");
				continue;
			}
			wait_handles[*nb_wait_handles] = fd->overlapped.hEvent;
			(*nb_wait_handles)++;
		}
	}

	usbi_mutex_static_unlock(&fd_table_lock);

	return nready;
}
/*
 * POSIX poll equivalent, using Windows OVERLAPPED
 * Currently, this function only accepts one of POLLIN or POLLOUT per fd
 * (but you can create multiple fds from the same handle for read and write)
 */
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
	HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
	DWORD nb_wait_handles = 0;
	DWORD ret;
	int nready;

	nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);

	// If nothing was triggered, wait on all fds that require it
	if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
		ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
			FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
		if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
			nready = check_pollfds(fds, nfds, NULL, NULL);
		} else if (ret != WAIT_TIMEOUT) {
			if (ret == WAIT_FAILED)
				usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
			nready = -1;
		}
	}

	return nready;
}

/*
 * close a fake file descriptor
 */
int usbi_close(int _fd)
{
	struct file_descriptor *fd;

	if (_fd < 0 || _fd >= fd_size)
		goto err_badfd;

	usbi_mutex_static_lock(&fd_table_lock);
	fd = fd_table[_fd];
	fd->refcount--;
	//FD_TYPE_PIPE map fd to two _fd
	if(fd->refcount==0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
	{	fd_table[_fd] = NULL;
		usbi_dec_fd_table();

		if (fd->type == FD_TYPE_PIPE) {
			// InternalHigh is our reference count
			fd->overlapped.InternalHigh--;
			if (fd->overlapped.InternalHigh == 0)
				free_fd(fd);
		}
		else {
			free_fd(fd);
		}
	}
	usbi_mutex_static_unlock(&fd_table_lock);

	if (fd == NULL)
		goto err_badfd;

	return 0;

err_badfd:
	errno = EBADF;
	return -1;
}

/*
* Create a fake pipe.
* As libusb only uses pipes for signaling, all we need from a pipe is an
* event. To that extent, we create a single wfd and overlapped as a means
* to access that event.
*/
int usbi_pipe(int filedes[2])
{
	struct file_descriptor *fd;
	int r_fd = -1, w_fd = -1;
	int i;

	fd = create_fd(FD_TYPE_PIPE);
	if (fd == NULL) {
		errno = ENOMEM;
		return -1;
	}

	// Use InternalHigh as a reference count
	fd->overlapped.Internal = STATUS_PENDING;
	fd->overlapped.InternalHigh = 2;

	usbi_mutex_static_lock(&fd_table_lock);
	do {
		smart_realloc_fd_table_space(2);

		for (i = 0; i < fd_size; i++) {
			if (fd_table[i] != NULL)
				continue;
			if (r_fd == -1) {
				r_fd = i;
			} else if (w_fd == -1) {
				w_fd = i;
				break;
			}
		}

		if (i == fd_size)
			break;

		fd_table[r_fd] = fd;
		fd_table[w_fd] = fd;

		fd->refcount++; //this fd reference twice for r and w.

		fd_count += 2;

	} while (0);
	usbi_mutex_static_unlock(&fd_table_lock);

	if (i == fd_size) {
		free_fd(fd);
		errno = EMFILE;
		return -1;
	}

	filedes[0] = r_fd;
	filedes[1] = w_fd;

	return 0;
}

/*
 * synchronous write for fake "pipe" signaling
 */
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
	int error = EBADF;

	UNUSED(buf);

	if (fd < 0 || fd >= fd_size)
		goto err_out;

	if (count != sizeof(unsigned char)) {
		usbi_err(NULL, "this function should only used for signaling");
		error = EINVAL;
		goto err_out;
	}

	usbi_mutex_static_lock(&fd_table_lock);
	if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
		assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
		assert(fd_table[fd]->overlapped.InternalHigh == 2);
		fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
		SetEvent(fd_table[fd]->overlapped.hEvent);
		error = 0;
	}
	usbi_mutex_static_unlock(&fd_table_lock);

	if (error)
		goto err_out;

	return sizeof(unsigned char);

err_out:
	errno = error;
	return -1;
}

/*
 * synchronous read for fake "pipe" signaling
 */
ssize_t usbi_read(int fd, void *buf, size_t count)
{
	int error = EBADF;

	UNUSED(buf);

	if (fd < 0 || fd >= fd_size)
		goto err_out;

	if (count != sizeof(unsigned char)) {
		usbi_err(NULL, "this function should only used for signaling");
		error = EINVAL;
		goto err_out;
	}

	usbi_mutex_static_lock(&fd_table_lock);
	if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
		assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
		assert(fd_table[fd]->overlapped.InternalHigh == 2);
		fd_table[fd]->overlapped.Internal = STATUS_PENDING;
		ResetEvent(fd_table[fd]->overlapped.hEvent);
		error = 0;
	}
	usbi_mutex_static_unlock(&fd_table_lock);

	if (error)
		goto err_out;

	return sizeof(unsigned char);

err_out:
	errno = error;
	return -1;
}
