/*
 * Copyright (c) 2019 Peter Bigot Consulting, LLC
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel.h>
#include <sys/onoff.h>
#include <stdio.h>

#define SERVICE_REFS_MAX UINT16_MAX

/* Confirm consistency of public flags with private flags */
BUILD_ASSERT((ONOFF_FLAG_ERROR | ONOFF_FLAG_ONOFF | ONOFF_FLAG_TRANSITION)
	     < BIT(3));

#define ONOFF_FLAG_PROCESSING BIT(3)
#define ONOFF_FLAG_COMPLETE BIT(4)
#define ONOFF_FLAG_RECHECK BIT(5)

/* These symbols in the ONOFF_FLAGS namespace identify bits in
 * onoff_manager::flags that indicate the state of the machine.  The
 * bits are manipulated by process_event() under lock, and actions
 * cued by bit values are executed outside of lock within
 * process_event().
 *
 * * ERROR indicates that the machine is in an error state.  When
 *   this bit is set ONOFF will be cleared.
 * * ONOFF indicates whether the target/current state is off (clear)
 *   or on (set).
 * * TRANSITION indicates whether a service transition function is in
 *   progress.  It combines with ONOFF to identify start and stop
 *   transitions, and with ERROR to identify a reset transition.
 * * PROCESSING indicates that the process_event() loop is active.  It
 *   is used to defer initiation of transitions and other complex
 *   state changes while invoking notifications associated with a
 *   state transition.  This bounds the  depth by limiting
 *   active process_event() call stacks to two instances.  State changes
 *   initiated by a nested call will be executed when control returns
 *   to the parent call.
 * * COMPLETE indicates that a transition completion notification has
 *   been received.  This flag is set in the notification, and cleared
 *   by process_events() which is invoked from the notification.  In
 *   the case of nested process_events() the processing is deferred to
 *   the top invocation.
 * * RECHECK indicates that a state transition has completed but
 *   process_events() must re-check the overall state to confirm no
 *   additional transitions are required.  This is used to simplfy the
 *   logic when, for example, a request is received during a
 *   transition to off, which means that when the transition completes
 *   a transition to on must be initiated if the request is still
 *   present.  Transition to ON with no remaining requests similarly
 *   triggers a recheck.
 */

/* Identify the events that can trigger state changes, as well as an
 * internal state used when processing deferred actions.
 */
enum event_type {
	/* No-op event: used to process deferred changes.
	 *
	 * This event is local to the process loop.
	 */
	EVT_NOP,

	/* Completion of a service transition.
	 *
	 * This event is triggered by the transition notify callback.
	 * It can be received only when the machine is in a transition
	 * state (TO-ON, TO-OFF, or RESETTING).
	 */
	EVT_COMPLETE,

	/* Reassess whether a transition from a stable state is needed.
	 *
	 * This event causes:
	 * * a start from OFF when there are clients;
	 * * a stop from ON when there are no clients;
	 * * a reset from ERROR when there are clients.
	 *
	 * The client list can change while the manager lock is
	 * released (e.g. during client and monitor notifications and
	 * transition initiations), so this event records the
	 * potential for these state changes, and process_event() ...
	 *
	 */
	EVT_RECHECK,

	/* Transition to on.
	 *
	 * This is synthesized from EVT_RECHECK in a non-nested
	 * process_event() when state OFF is confirmed with a
	 * non-empty client (request) list.
	 */
	EVT_START,

	/* Transition to off.
	 *
	 * This is synthesized from EVT_RECHECK in a non-nested
	 * process_event() when state ON is confirmed with a
	 * zero reference count.
	 */
	EVT_STOP,

	/* Transition to resetting.
	 *
	 * This is synthesized from EVT_RECHECK in a non-nested
	 * process_event() when state ERROR is confirmed with a
	 * non-empty client (reset) list.
	 */
	EVT_RESET,
};

static void set_state(struct onoff_manager *mgr,
		      u32_t state)
{
	mgr->flags = (state & ONOFF_STATE_MASK)
		     | (mgr->flags & ~ONOFF_STATE_MASK);
}

static int validate_args(const struct onoff_manager *mgr,
			 struct onoff_client *cli)
{
	if ((mgr == NULL) || (cli == NULL)) {
		return -EINVAL;
	}

	int rv = sys_notify_validate(&cli->notify);

	if ((rv == 0)
	    && ((cli->notify.flags
		 & ~BIT_MASK(ONOFF_CLIENT_EXTENSION_POS)) != 0)) {
		rv = -EINVAL;
	}

	return rv;
}

int onoff_manager_init(struct onoff_manager *mgr,
		       const struct onoff_transitions *transitions)
{
	if ((mgr == NULL)
	    || (transitions == NULL)
	    || (transitions->start == NULL)
	    || (transitions->stop == NULL)) {
		return -EINVAL;
	}

	*mgr = (struct onoff_manager)ONOFF_MANAGER_INITIALIZER(transitions);

	return 0;
}

static void notify_monitors(struct onoff_manager *mgr,
			    u32_t state,
			    int res)
{
	sys_slist_t *mlist = &mgr->monitors;
	struct onoff_monitor *mon;
	struct onoff_monitor *tmp;

	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(mlist, mon, tmp, node) {
		mon->callback(mgr, mon, state, res);
	}
}

static void notify_one(struct onoff_manager *mgr,
		       struct onoff_client *cli,
		       u32_t state,
		       int res)
{
	onoff_client_callback cb =
		(onoff_client_callback)sys_notify_finalize(&cli->notify, res);

	if (cb) {
		cb(mgr, cli, state, res);
	}
}

static void notify_all(struct onoff_manager *mgr,
		       sys_slist_t *list,
		       u32_t state,
		       int res)
{
	while (!sys_slist_is_empty(list)) {
		sys_snode_t *node = sys_slist_get_not_empty(list);
		struct onoff_client *cli =
			CONTAINER_OF(node,
				     struct onoff_client,
				     node);

		notify_one(mgr, cli, state, res);
	}
}

static void process_event(struct onoff_manager *mgr,
			  int evt,
			  k_spinlock_key_t key);

static void transition_complete(struct onoff_manager *mgr,
				int res)
{
	k_spinlock_key_t key = k_spin_lock(&mgr->lock);

	mgr->last_res = res;
	process_event(mgr, EVT_COMPLETE, key);
}

/* Detect whether static state requires a transition. */
static int process_recheck(struct onoff_manager *mgr)
{
	int evt = EVT_NOP;
	u32_t state = mgr->flags & ONOFF_STATE_MASK;

	if ((state == ONOFF_STATE_OFF)
	    && !sys_slist_is_empty(&mgr->clients)) {
		evt = EVT_START;
	} else if ((state == ONOFF_STATE_ON)
		   && (mgr->refs == 0)) {
		evt = EVT_STOP;
	} else if ((state == ONOFF_STATE_ERROR)
		   && !sys_slist_is_empty(&mgr->clients)) {
		evt = EVT_RESET;
	}

	return evt;
}

/* Process a transition completion.
 *
 * If the completion requires notifying clients, the clients are moved
 * from the manager to the output list for notification.
 */
static void process_complete(struct onoff_manager *mgr,
			     sys_slist_t *clients,
			     int res)
{
	u32_t state = mgr->flags & ONOFF_STATE_MASK;

	if (res < 0) {
		/* Enter ERROR state and notify all clients. */
		*clients = mgr->clients;
		sys_slist_init(&mgr->clients);
		set_state(mgr, ONOFF_STATE_ERROR);
	} else if ((state == ONOFF_STATE_TO_ON)
		   || (state == ONOFF_STATE_RESETTING)) {
		*clients = mgr->clients;
		sys_slist_init(&mgr->clients);

		if (state == ONOFF_STATE_TO_ON) {
			struct onoff_client *cp;

			/* Increment reference count for all remaining
			 * clients and enter ON state.
			 */
			SYS_SLIST_FOR_EACH_CONTAINER(clients, cp, node) {
				mgr->refs += 1U;
			}

			set_state(mgr, ONOFF_STATE_ON);
		} else {
			__ASSERT_NO_MSG(state == ONOFF_STATE_RESETTING);

			set_state(mgr, ONOFF_STATE_OFF);
		}
		if (process_recheck(mgr) != EVT_NOP) {
			mgr->flags |= ONOFF_FLAG_RECHECK;
		}
	} else if (state == ONOFF_STATE_TO_OFF) {
		/* Any active clients are requests waiting for this
		 * transition to complete.  Queue a RECHECK event to
		 * ensure we don't miss them if we don't unlock to
		 * tell anybody about the completion.
		 */
		set_state(mgr, ONOFF_STATE_OFF);
		if (process_recheck(mgr) != EVT_NOP) {
			mgr->flags |= ONOFF_FLAG_RECHECK;
		}
	} else {
		__ASSERT_NO_MSG(false);
	}
}

/* There are two points in the state machine where the machine is
 * unlocked to perform some external action:
 * * Initiation of an transition due to some event;
 * * Invocation of the user-specified callback when a stable state is
 *   reached or an error detected.
 *
 * Events received during these unlocked periods are recorded in the
 * state, but processing is deferred to the top-level invocation which
 * will loop to handle any events that occurred during the unlocked
 * regions.
 */
static void process_event(struct onoff_manager *mgr,
			  int evt,
			  k_spinlock_key_t key)
{
	sys_slist_t clients;
	u32_t state = mgr->flags & ONOFF_STATE_MASK;
	int res = 0;
	bool processing = ((mgr->flags & ONOFF_FLAG_PROCESSING) != 0);

	__ASSERT_NO_MSG(evt != EVT_NOP);

	/* If this is a nested call record the event for processing in
	 * the top invocation.
	 */
	if (processing) {
		if (evt == EVT_COMPLETE) {
			mgr->flags |= ONOFF_FLAG_COMPLETE;
		} else {
			__ASSERT_NO_MSG(evt == EVT_RECHECK);

			mgr->flags |= ONOFF_FLAG_RECHECK;
		}

		goto out;
	}

	sys_slist_init(&clients);
	do {
		onoff_transition_fn transit = NULL;

		if (evt == EVT_RECHECK) {
			evt = process_recheck(mgr);
		}

		if (evt == EVT_NOP) {
			break;
		}

		res = 0;
		if (evt == EVT_COMPLETE) {
			res = mgr->last_res;
			process_complete(mgr, &clients, res);
			/* NB: This can trigger a RECHECK */
		} else if (evt == EVT_START) {
			__ASSERT_NO_MSG(state == ONOFF_STATE_OFF);
			__ASSERT_NO_MSG(!sys_slist_is_empty(&mgr->clients));

			transit = mgr->transitions->start;
			__ASSERT_NO_MSG(transit != NULL);
			set_state(mgr, ONOFF_STATE_TO_ON);
		} else if (evt == EVT_STOP) {
			__ASSERT_NO_MSG(state == ONOFF_STATE_ON);
			__ASSERT_NO_MSG(mgr->refs == 0);

			transit = mgr->transitions->stop;
			__ASSERT_NO_MSG(transit != NULL);
			set_state(mgr, ONOFF_STATE_TO_OFF);
		} else if (evt == EVT_RESET) {
			__ASSERT_NO_MSG(state == ONOFF_STATE_ERROR);
			__ASSERT_NO_MSG(!sys_slist_is_empty(&mgr->clients));

			transit = mgr->transitions->reset;
			__ASSERT_NO_MSG(transit != NULL);
			set_state(mgr, ONOFF_STATE_RESETTING);
		} else {
			__ASSERT_NO_MSG(false);
		}

		/* Have to unlock and do something if any of:
		 * * We changed state and there are monitors;
		 * * We completed a transition and there are clients to notify;
		 * * We need to initiate a transition.
		 */
		bool do_monitors = (state != (mgr->flags & ONOFF_STATE_MASK))
				   && !sys_slist_is_empty(&mgr->monitors);

		evt = EVT_NOP;
		if (do_monitors
		    || !sys_slist_is_empty(&clients)
		    || (transit != NULL)) {
			u32_t flags = mgr->flags | ONOFF_FLAG_PROCESSING;

			mgr->flags = flags;
			state = flags & ONOFF_STATE_MASK;

			k_spin_unlock(&mgr->lock, key);

			if (do_monitors) {
				notify_monitors(mgr, state, res);
			}

			if (!sys_slist_is_empty(&clients)) {
				notify_all(mgr, &clients, state, res);
			}

			if (transit != NULL) {
				transit(mgr, transition_complete);
			}

			key = k_spin_lock(&mgr->lock);
			mgr->flags &= ~ONOFF_FLAG_PROCESSING;
			state = mgr->flags & ONOFF_STATE_MASK;
		}

		/* Process deferred events.  Completion takes priority
		 * over recheck.
		 */
		if ((mgr->flags & ONOFF_FLAG_COMPLETE) != 0) {
			mgr->flags &= ~ONOFF_FLAG_COMPLETE;
			evt = EVT_COMPLETE;
		} else if ((mgr->flags & ONOFF_FLAG_RECHECK) != 0) {
			mgr->flags &= ~ONOFF_FLAG_RECHECK;
			evt = EVT_RECHECK;
		}

		state = mgr->flags & ONOFF_STATE_MASK;
	} while (evt != EVT_NOP);

out:
	k_spin_unlock(&mgr->lock, key);
}

int onoff_request(struct onoff_manager *mgr,
		  struct onoff_client *cli)
{
	bool add_client = false;        /* add client to pending list */
	bool start = false;             /* trigger a start transition */
	bool notify = false;            /* do client notification */
	int rv = validate_args(mgr, cli);

	if (rv < 0) {
		return rv;
	}

	k_spinlock_key_t key = k_spin_lock(&mgr->lock);
	u32_t state = mgr->flags & ONOFF_STATE_MASK;

	/* Reject if this would overflow the reference count. */
	if (mgr->refs == SERVICE_REFS_MAX) {
		rv = -EAGAIN;
		goto out;
	}

	rv = state;
	if (state == ONOFF_STATE_ON) {
		/* Increment reference count, notify in exit */
		notify = true;
		mgr->refs += 1U;
	} else if ((state == ONOFF_STATE_OFF)
		   || (state == ONOFF_STATE_TO_OFF)
		   || (state == ONOFF_STATE_TO_ON)) {
		/* Start if OFF, queue client */
		start = (state == ONOFF_STATE_OFF);
		add_client = true;
	} else if (state == ONOFF_STATE_RESETTING) {
		rv = -ENOTSUP;
	} else {
		__ASSERT_NO_MSG(state == ONOFF_STATE_ERROR);
		rv = -EIO;
	}

out:
	if (add_client) {
		sys_slist_append(&mgr->clients, &cli->node);
	}

	if (start) {
		process_event(mgr, EVT_RECHECK, key);
	} else {
		k_spin_unlock(&mgr->lock, key);

		if (notify) {
			notify_one(mgr, cli, state, 0);
		}
	}

	return rv;
}

int onoff_release(struct onoff_manager *mgr)
{
	bool stop = false;      /* trigger a stop transition */

	k_spinlock_key_t key = k_spin_lock(&mgr->lock);
	u32_t state = mgr->flags & ONOFF_STATE_MASK;
	int rv = state;

	if (state != ONOFF_STATE_ON) {
		if (state == ONOFF_STATE_ERROR) {
			rv = -EIO;
		} else {
			rv = -ENOTSUP;
		}
		goto out;
	}

	__ASSERT_NO_MSG(mgr->refs > 0);
	mgr->refs -= 1U;
	stop = (mgr->refs == 0);

out:
	if (stop) {
		process_event(mgr, EVT_RECHECK, key);
	} else {
		k_spin_unlock(&mgr->lock, key);
	}

	return rv;
}

int onoff_reset(struct onoff_manager *mgr,
		struct onoff_client *cli)
{
	bool reset = false;
	int rv = validate_args(mgr, cli);

	if ((rv >= 0)
	    && (mgr->transitions->reset == NULL)) {
		rv = -ENOTSUP;
	}

	if (rv < 0) {
		return rv;
	}

	k_spinlock_key_t key = k_spin_lock(&mgr->lock);
	u32_t state = mgr->flags & ONOFF_STATE_MASK;

	rv = state;

	if ((state & ONOFF_FLAG_ERROR) == 0) {
		rv = -EALREADY;
	} else {
		reset = (state != ONOFF_STATE_RESETTING);
		sys_slist_append(&mgr->clients, &cli->node);
	}

	if (reset) {
		process_event(mgr, EVT_RECHECK, key);
	} else {
		k_spin_unlock(&mgr->lock, key);
	}

	return rv;
}

int onoff_cancel(struct onoff_manager *mgr,
		 struct onoff_client *cli)
{
	if ((mgr == NULL) || (cli == NULL)) {
		return -EINVAL;
	}

	int rv = -EALREADY;
	k_spinlock_key_t key = k_spin_lock(&mgr->lock);
	u32_t state = mgr->flags & ONOFF_STATE_MASK;

	if (sys_slist_find_and_remove(&mgr->clients, &cli->node)) {
		__ASSERT_NO_MSG((state == ONOFF_STATE_TO_ON)
				|| (state == ONOFF_STATE_TO_OFF)
				|| (state == ONOFF_STATE_RESETTING));
		rv = state;
	}

	k_spin_unlock(&mgr->lock, key);

	return rv;
}

int onoff_monitor_register(struct onoff_manager *mgr,
			   struct onoff_monitor *mon)
{
	if ((mgr == NULL)
	    || (mon == NULL)
	    || (mon->callback == NULL)) {
		return -EINVAL;
	}

	k_spinlock_key_t key = k_spin_lock(&mgr->lock);

	sys_slist_append(&mgr->monitors, &mon->node);

	k_spin_unlock(&mgr->lock, key);

	return 0;
}

int onoff_monitor_unregister(struct onoff_manager *mgr,
			     struct onoff_monitor *mon)
{
	int rv = -EINVAL;

	if ((mgr == NULL)
	    || (mon == NULL)) {
		return rv;
	}

	k_spinlock_key_t key = k_spin_lock(&mgr->lock);

	if (sys_slist_find_and_remove(&mgr->monitors, &mon->node)) {
		rv = 0;
	}

	k_spin_unlock(&mgr->lock, key);

	return rv;
}
