/*
 * Copyright (c) 2019 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <vppinfra/fifo.h>
#include <vppinfra/pool.h>
#include <vppinfra/hash.h>
#include <vnet/api_errno.h>

#include <vcl/vcl_event.h>
/**
 * @file
 * @brief VPP Communications Library (VCL) event handler.
 *
 * Definitions for generic event handling in VCL.
 */

int
vce_generate_event (vce_event_thread_t *evt, u32 ev_idx)
{
  int elts, rv = 0;
  vce_event_t *p;

  pthread_mutex_lock (&(evt->generator_lock));

  /* Check there is event data for this event */

  clib_spinlock_lock (&(evt->events_lockp));
  p =  pool_elt_at_index (evt->vce_events, ev_idx);
  ASSERT(p);

  elts = (int) clib_fifo_free_elts (evt->event_index_fifo);
  if (PREDICT_TRUE (elts))
    {
      /* Add event to queue */
      clib_fifo_add1 (evt->event_index_fifo, ev_idx);
      pthread_cond_signal (&(evt->generator_cond));
    }
  else
    {
      rv = VNET_API_ERROR_QUEUE_FULL;
    }

  clib_spinlock_unlock (&(evt->events_lockp));
  pthread_mutex_unlock (&(evt->generator_lock));

  return rv;
}

void
vce_clear_event (vce_event_thread_t *evt, vce_event_t *ev)
{
  clib_spinlock_lock (&(evt->events_lockp));
  pool_put (evt->vce_events, ev);
  clib_spinlock_unlock (&(evt->events_lockp));
}

vce_event_t *
vce_get_event_from_index(vce_event_thread_t *evt, u32 ev_idx)
{
  vce_event_t *ev = 0;

  clib_spinlock_lock (&(evt->events_lockp));
  if ( ! pool_is_free_index (evt->vce_events, ev_idx))
    ev = pool_elt_at_index (evt->vce_events, ev_idx);
  clib_spinlock_unlock (&(evt->events_lockp));

  return ev;
}

vce_event_handler_reg_t *
vce_get_event_handler (vce_event_thread_t *evt, vce_event_key_t *evk)
{
  vce_event_handler_reg_t *handler = 0;
  uword *p;

  clib_spinlock_lock (&evt->handlers_lockp);
  p = hash_get (evt->handlers_index_by_event_key, evk->as_u64);
  if (p)
    handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
  clib_spinlock_unlock (&evt->handlers_lockp);

  return handler;
}

vce_event_handler_reg_t *
vce_register_handler (vce_event_thread_t *evt, vce_event_key_t *evk,
		      vce_event_callback_t cb, void *cb_args)
{
  vce_event_handler_reg_t *handler;
  vce_event_handler_reg_t *old_handler = 0;
  uword *p;
  u32 handler_index;

  /* TODO - multiple handler support. For now we can replace
   * and re-instate, which is useful for event recycling */

  clib_spinlock_lock (&evt->handlers_lockp);

  p = hash_get (evt->handlers_index_by_event_key, evk->as_u64);
  if (p)
    {
      old_handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
      /* If we are just re-registering, ignore and move on
       * else store the old handler_fn for unregister to re-instate */
      if (old_handler->handler_fn == cb)
	{

	  clib_spinlock_unlock (&evt->handlers_lockp);

	  /* Signal event thread that a handler exists in case any
	   * recycled events requiring this handler are pending */
	  pthread_mutex_lock (&(evt->generator_lock));
	  pthread_cond_signal (&(evt->generator_cond));
	  pthread_mutex_unlock (&(evt->generator_lock));
	  return old_handler;
	}
    }

  pool_get (evt->vce_event_handlers, handler);
  handler_index = (u32) (handler - evt->vce_event_handlers);

  handler->handler_fn = cb;
  handler->replaced_handler_idx = (p) ? p[0] : ~0;
  handler->ev_idx = ~0; //This will be set by the event thread if event happens
  handler->evk = evk->as_u64;
  handler->handler_fn_args = cb_args;

  hash_set (evt->handlers_index_by_event_key, evk->as_u64, handler_index);

  pthread_cond_init (&(handler->handler_cond), NULL);
  pthread_mutex_init (&(handler->handler_lock), NULL);

  clib_spinlock_unlock (&evt->handlers_lockp);

  /* Signal event thread that a new handler exists in case any
   * recycled events requiring this handler are pending */
  pthread_mutex_lock (&(evt->generator_lock));
  pthread_cond_signal (&(evt->generator_cond));
  pthread_mutex_unlock (&(evt->generator_lock));

  return handler;
}

int
vce_unregister_handler (vce_event_thread_t *evt,
			vce_event_handler_reg_t *handler)
{
  uword *p;
  u64 evk = handler->evk;
  u8 generate_signal = 0;

  clib_spinlock_lock (&evt->handlers_lockp);

  p = hash_get (evt->handlers_index_by_event_key, evk);
  if (!p)
    {
      clib_spinlock_unlock (&evt->handlers_lockp);
      return VNET_API_ERROR_NO_SUCH_ENTRY;
    }

  handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);

  /* If this handler replaced another handler, re-instate it */
  if (handler->replaced_handler_idx != ~0)
    {
      hash_set (evt->handlers_index_by_event_key, evk,
		handler->replaced_handler_idx);
      generate_signal = 1;
    }
  else
    {
      hash_unset (evt->handlers_index_by_event_key, evk);
    }

  pthread_mutex_destroy (&(handler->handler_lock));
  pthread_cond_destroy (&(handler->handler_cond));
  pool_put (evt->vce_event_handlers, handler);

  clib_spinlock_unlock (&evt->handlers_lockp);

  if (generate_signal)
    {
      /* Signal event thread that a new handler exists in case any
       * recycled events requiring this handler are pending */
      pthread_mutex_lock (&(evt->generator_lock));
      pthread_cond_signal (&(evt->generator_cond));
      pthread_mutex_unlock (&(evt->generator_lock));
    }

  return 0;
}

void *
vce_event_thread_fn (void *arg)
{
  vce_event_thread_t *evt = (vce_event_thread_t *) arg;
  vce_event_t *ev;
  u32 ev_idx;
  vce_event_handler_reg_t *handler;
  uword *p;

  pthread_mutex_lock (&(evt->generator_lock));
  clib_spinlock_lock (&(evt->events_lockp));
  evt->recycle_event = 1; // Used for recycling events with no handlers
  clib_spinlock_unlock (&(evt->events_lockp));

  do
    {
      while ( (clib_fifo_elts (evt->event_index_fifo) == 0) ||
	      evt->recycle_event)
	{
          clib_spinlock_lock (&(evt->events_lockp));
	  evt->recycle_event = 0;
          clib_spinlock_unlock (&(evt->events_lockp));
	  pthread_cond_wait (&(evt->generator_cond),
			     &(evt->generator_lock));
	}

      /* Remove event */
      clib_spinlock_lock (&(evt->events_lockp));

      clib_fifo_sub1 (evt->event_index_fifo, ev_idx);
      ev = pool_elt_at_index (evt->vce_events, ev_idx);

      ASSERT(ev);

      clib_spinlock_lock (&evt->handlers_lockp);

      p = hash_get (evt->handlers_index_by_event_key, ev->evk.as_u64);
      if (!p)
	{
	  /* If an event falls in the woods, and there is no handler to hear it,
	   * does it make any sound?
	   * I don't know either, so lets try recycling the event */
	  clib_fifo_add1 (evt->event_index_fifo, ev_idx);
	  evt->recycle_event = 1;
          clib_spinlock_unlock (&(evt->events_lockp));
	  clib_spinlock_unlock (&evt->handlers_lockp);
          pthread_mutex_unlock (&(evt->generator_lock));
	}
      else
        {
          handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
          handler->ev_idx = ev_idx;

          clib_spinlock_unlock (&(evt->events_lockp));
          clib_spinlock_unlock (&evt->handlers_lockp);
          pthread_mutex_unlock (&(evt->generator_lock));

          (handler->handler_fn)(handler);
        }

      pthread_mutex_lock (&(evt->generator_lock));
    }
  while (1);
  return NULL;
}

int
vce_start_event_thread (vce_event_thread_t *evt, u8 max_events)
{
  clib_fifo_validate (evt->event_index_fifo, max_events);
  evt->handlers_index_by_event_key = hash_create (0, sizeof (uword));

  pthread_cond_init (&(evt->generator_cond), NULL);
  pthread_mutex_init (&(evt->generator_lock), NULL);

  clib_spinlock_init (&(evt->events_lockp));
  clib_spinlock_init (&(evt->handlers_lockp));

  return pthread_create (&(evt->thread), NULL /* attr */ ,
			 vce_event_thread_fn, evt);
}
