/*!
 * (C) Copyright 2003-2018 Awox SA.  All rights reserved.
 * This work contains confidential trade secrets of Awox.
 * Use, examination, copying, transfer and disclosure to others
 * are prohibited, except with the express written agreement of Awox.
 *
 * @Author:  Awox
 * @Date: 08/10/2014
 */

/*------------------------------- INCLUDES ----------------------------------*/

#include <stdint.h>
#include <stdio.h>

extern "C" {
#include <libubox/blobmsg_json.h>
#include "ubus-sync.h"
}

#include "ubus-cpp/ubus-event.h"

/*------------------------------- GLOBALS ----------------------------------*/

/*--------------------------------- DEFINES ---------------------------------*/

// #define UBUS_PROFILE 1

static void receive_event(struct ubus_context *a_ctx, struct ubus_event_handler *an_ev,
						  const char *a_type, struct blob_attr *a_msg)
{
	char *the_str;
	UBusEvent *a_caller = static_cast<UBusEvent *>(an_ev->priv);

	the_str = blobmsg_format_json(a_msg, true);

	a_caller->handle_event(a_type, the_str);

	free(the_str);
}

/*!  ----------------------------------------------------------------------------
 *  @fn UBusEvent
 *
 *  @brief Constructor of the UBusEvent
 */
UBusEvent::UBusEvent(void)
{
}

/*!  ----------------------------------------------------------------------------
 *  @fn ~UBusEvent
 *
 *  @brief Destructor of the UBusEvent
 */
UBusEvent::~UBusEvent(void)
{
	while (!m_listeners.empty())
	{
		delete *(m_listeners.begin());
		m_listeners.erase(m_listeners.begin());
	}
}

/*!  ----------------------------------------------------------------------------
 *  @fn listen
 *
 *  @brief Handle an UBUS Event.
 */
int UBusEvent::listen(struct ubus_context *a_ctx, const std::string &an_event)
{
	//static struct ubus_event_handler theListener;
	//fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);

	struct ubus_event_handler *the_evt_listener = new ubus_event_handler;

	memset(the_evt_listener, 0, sizeof(struct ubus_event_handler));
	the_evt_listener->cb = receive_event;
	the_evt_listener->priv = this;

	m_listeners.push_back(the_evt_listener);

	return ubus_register_event_handler(a_ctx, the_evt_listener, an_event.c_str());
}

/*!  ----------------------------------------------------------------------------
 *  @fn handle_event
 *
 *  @brief Handle an UBUS Event.
 */
void UBusEvent::handle_event(const char *a_type, const char *a_json_msg)
{
}

/*!  ----------------------------------------------------------------------------
 *  @fn send
 *
 *  @brief Send an UBus Method
 */
int UBusEvent::send(const std::string &an_event, const std::string &a_data)
{
	int the_result;
#ifdef UBUS_PROFILE
	struct timeval the_start_request, the_current_timeval;
	gettimeofday(&the_start_request, NULL);
#endif

	the_result = ubus_sync_send_event(an_event.c_str(), a_data.c_str());

#ifdef UBUS_PROFILE
	gettimeofday(&the_current_timeval, NULL);
	printf("ubus_event [%s] duree: %.0lf ms\n", an_event.c_str(), time_diff(the_start_request, the_current_timeval) / 1000);
#endif

	return the_result;
}
