/*
 * Copyright 2001-2010 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Ingo Weinhold, bonefish@@users.sf.net
 *		Axel Dörfler, axeld@pinc-software.de
 *		Clemens Zeidler <haiku@clemens-zeidler.de>
 */


#include <Messenger.h>
#include <NodeMonitor.h>

#include <MessengerPrivate.h>

#include <syscalls.h>

#ifndef HoG_GENODE
#include "node_monitor_private.h"
#endif  // ~HoG_GENODE


// TODO: Tests!


// Subscribes a target to watch node changes on a volume.
status_t
watch_volume(dev_t /*volume*/, uint32 /*flags*/, BMessenger /*target*/)
{
///later: watch_node(), watch_volume() etc
#ifndef HoG_GENODE
	if ((flags & (B_WATCH_NAME | B_WATCH_STAT | B_WATCH_ATTR)) == 0)
		return B_BAD_VALUE;

	flags |= B_WATCH_VOLUME;

	BMessenger::Private messengerPrivate(target);
	port_id port = messengerPrivate.Port();
	int32 token = messengerPrivate.Token();
	return _kern_start_watching(volume, (ino_t)-1, flags, port, token);
#else  // HoG_GENODE
	return -1;
#endif  // ~HoG_GENODE
}


status_t
watch_volume(dev_t volume, uint32 flags, const BHandler* handler,
	const BLooper* looper)
{
	return watch_volume(volume, flags, BMessenger(handler, looper));
}


// Subscribes or unsubscribes a target to node and/or mount watching.
status_t
watch_node(const node_ref* /*node*/, uint32 /*flags*/, BMessenger target)
{
	if (!target.IsValid())
		return B_BAD_VALUE;

#ifndef HoG_GENODE
	BMessenger::Private messengerPrivate(target);
	port_id port = messengerPrivate.Port();
	int32 token = messengerPrivate.Token();

	if (flags == B_STOP_WATCHING) {
		// unsubscribe from node node watching
		if (node == NULL)
			return B_BAD_VALUE;

		return _kern_stop_watching(node->device, node->node, port, token);
	}

	// subscribe to...
	// mount watching
	if (flags & B_WATCH_MOUNT) {
		status_t status = _kern_start_watching((dev_t)-1, (ino_t)-1,
			B_WATCH_MOUNT, port, token);
		if (status < B_OK)
			return status;

		flags &= ~B_WATCH_MOUNT;
	}

	// node watching
	if (flags != 0) {
		if (node == NULL)
			return B_BAD_VALUE;

		return _kern_start_watching(node->device, node->node, flags, port,
			token);
	}
#endif  // ~HoG_GENODE

	return B_OK;
}


// Subscribes or unsubscribes a handler or looper to node and/or mount
// watching.
status_t
watch_node(const node_ref* node, uint32 flags, const BHandler* handler,
	const BLooper* looper)
{
	return watch_node(node, flags, BMessenger(handler, looper));
}


// Unsubscribes a target from node and mount monitoring.
status_t
stop_watching(BMessenger target)
{
	if (!target.IsValid())
		return B_BAD_VALUE;

#ifndef HoG_GENODE
	BMessenger::Private messengerPrivate(target);
	port_id port = messengerPrivate.Port();
	int32 token = messengerPrivate.Token();

	return _kern_stop_notifying(port, token);
#else  // HoG_GENODE
	return -1;
#endif  // ~HoG_GENODE
}


// Unsubscribes a target from node and mount monitoring.
status_t
stop_watching(const BHandler* handler, const BLooper* looper)
{
	return stop_watching(BMessenger(handler, looper));
}

