/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2012-2014  Intel Corporation. All rights reserved.
 *
 *
 *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>

#include "monitor/mainloop.h"
#include "src/shared/util.h"
#include "src/shared/io.h"

struct io {
	int ref_count;
	int fd;
	uint32_t events;
	bool close_on_destroy;
	io_callback_func_t read_callback;
	io_destroy_func_t read_destroy;
	void *read_data;
	io_callback_func_t write_callback;
	io_destroy_func_t write_destroy;
	void *write_data;
	io_callback_func_t disconnect_callback;
	io_destroy_func_t disconnect_destroy;
	void *disconnect_data;
};

static struct io *io_ref(struct io *io)
{
	if (!io)
		return NULL;

	__sync_fetch_and_add(&io->ref_count, 1);

	return io;
}

static void io_unref(struct io *io)
{
	if (!io)
		return;

	if (__sync_sub_and_fetch(&io->ref_count, 1))
		return;

	free(io);
}

static void io_cleanup(void *user_data)
{
	struct io *io = user_data;

	if (io->write_destroy)
		io->write_destroy(io->write_data);

	if (io->read_destroy)
		io->read_destroy(io->read_data);

	if (io->disconnect_destroy)
		io->disconnect_destroy(io->disconnect_data);

	if (io->close_on_destroy)
		close(io->fd);

	io->fd = -1;
}

static void io_callback(int fd, uint32_t events, void *user_data)
{
	struct io *io = user_data;

	io_ref(io);

	if ((events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))) {
		io->read_callback = NULL;
		io->write_callback = NULL;

		if (!io->disconnect_callback) {
			mainloop_remove_fd(io->fd);
			io_unref(io);
			return;
		}

		if (!io->disconnect_callback(io, io->disconnect_data)) {
			if (io->disconnect_destroy)
				io->disconnect_destroy(io->disconnect_data);

			io->disconnect_callback = NULL;
			io->disconnect_destroy = NULL;
			io->disconnect_data = NULL;

			io->events &= ~EPOLLRDHUP;

			mainloop_modify_fd(io->fd, io->events);
		}
	}

	if ((events & EPOLLIN) && io->read_callback) {
		if (!io->read_callback(io, io->read_data)) {
			if (io->read_destroy)
				io->read_destroy(io->read_data);

			io->read_callback = NULL;
			io->read_destroy = NULL;
			io->read_data = NULL;

			io->events &= ~EPOLLIN;

			mainloop_modify_fd(io->fd, io->events);
		}
	}

	if ((events & EPOLLOUT) && io->write_callback) {
		if (!io->write_callback(io, io->write_data)) {
			if (io->write_destroy)
				io->write_destroy(io->write_data);

			io->write_callback = NULL;
			io->write_destroy = NULL;
			io->write_data = NULL;

			io->events &= ~EPOLLOUT;

			mainloop_modify_fd(io->fd, io->events);
		}
	}

	io_unref(io);
}

struct io *io_new(int fd)
{
	struct io *io;

	if (fd < 0)
		return NULL;

	io = new0(struct io, 1);
	if (!io)
		return NULL;

	io->fd = fd;
	io->events = 0;
	io->close_on_destroy = false;

	if (mainloop_add_fd(io->fd, io->events, io_callback,
						io, io_cleanup) < 0) {
		free(io);
		return NULL;
	}

	return io_ref(io);
}

void io_destroy(struct io *io)
{
	if (!io)
		return;

	io->read_callback = NULL;
	io->write_callback = NULL;
	io->disconnect_callback = NULL;

	mainloop_remove_fd(io->fd);

	io_unref(io);
}

int io_get_fd(struct io *io)
{
	if (!io)
		return -ENOTCONN;

	return io->fd;
}

bool io_set_close_on_destroy(struct io *io, bool do_close)
{
	if (!io)
		return false;

	io->close_on_destroy = do_close;

	return true;
}

bool io_set_read_handler(struct io *io, io_callback_func_t callback,
				void *user_data, io_destroy_func_t destroy)
{
	uint32_t events;

	if (!io || io->fd < 0)
		return false;

	if (io->read_destroy)
		io->read_destroy(io->read_data);

	if (callback)
		events = io->events | EPOLLIN;
	else
		events = io->events & ~EPOLLIN;

	io->read_callback = callback;
	io->read_destroy = destroy;
	io->read_data = user_data;

	if (events == io->events)
		return true;

	if (mainloop_modify_fd(io->fd, events) < 0)
		return false;

	io->events = events;

	return true;
}

bool io_set_write_handler(struct io *io, io_callback_func_t callback,
				void *user_data, io_destroy_func_t destroy)
{
	uint32_t events;

	if (!io || io->fd < 0)
		return false;

	if (io->write_destroy)
		io->write_destroy(io->write_data);

	if (callback)
		events = io->events | EPOLLOUT;
	else
		events = io->events & ~EPOLLOUT;

	io->write_callback = callback;
	io->write_destroy = destroy;
	io->write_data = user_data;

	if (events == io->events)
		return true;

	if (mainloop_modify_fd(io->fd, events) < 0)
		return false;

	io->events = events;

	return true;
}

bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
				void *user_data, io_destroy_func_t destroy)
{
	uint32_t events;

	if (!io || io->fd < 0)
		return false;

	if (io->disconnect_destroy)
		io->disconnect_destroy(io->disconnect_data);

	if (callback)
		events = io->events | EPOLLRDHUP;
	else
		events = io->events & ~EPOLLRDHUP;

	io->disconnect_callback = callback;
	io->disconnect_destroy = destroy;
	io->disconnect_data = user_data;

	if (events == io->events)
		return true;

	if (mainloop_modify_fd(io->fd, events) < 0)
		return false;

	io->events = events;

	return true;
}

ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
{
	ssize_t ret;

	if (!io || io->fd < 0)
		return -ENOTCONN;

	do {
		ret = writev(io->fd, iov, iovcnt);
	} while (ret < 0 && errno == EINTR);

	if (ret < 0)
		return -errno;

	return ret;
}

bool io_shutdown(struct io *io)
{
	if (!io || io->fd < 0)
		return false;

	return shutdown(io->fd, SHUT_RDWR) == 0;
}
