/*!
 * UBusModel.c
 *
 * Copyright (c) 2015, NADAL Jean-Baptiste. 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 Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 * 
 * @Author:  NADAL Jean-Baptiste
 * @Date: 26/02/2015
 *
 */

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

#include <unistd.h>
#include <signal.h>

#include <libubox/blobmsg_json.h>
#include <libubus.h>

/*------------------------------- DECLARATION -------------------------------*/

static int gChacon_set (struct ubus_context *ctx, struct ubus_object *obj,
		      			struct ubus_request_data *req, const char *method,
		      			struct blob_attr *msg);

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


static struct ubus_context *gCtx;
static struct blob_buf gBuffer;

enum {
	SET_SENDER,
	SET_INTERRUPTOR,
	SET_STATE,
	__CHACON_MAX
};

static const struct blobmsg_policy set_chacon_policy[] = {
	[SET_SENDER] = { .name = "sender", .type = BLOBMSG_TYPE_INT32 },
	[SET_INTERRUPTOR] = { .name = "interruptor", .type = BLOBMSG_TYPE_INT32 },
	[SET_STATE] = { .name = "state", .type = BLOBMSG_TYPE_BOOL },
};

static const struct ubus_method gChacon_methods[] = {
	UBUS_METHOD("set", gChacon_set, set_chacon_policy),
};

static struct ubus_object_type gChacon_object_type =
	UBUS_OBJECT_TYPE ("chacon", gChacon_methods);

static struct ubus_object gChacon_object = {
	.name = "chacon",
	.type = &gChacon_object_type,
	.methods = gChacon_methods,
	.n_methods = ARRAY_SIZE (gChacon_methods),
};


/*!  ----------------------------------------------------------------------------
 *  @fn gChacon_set
 *
 *  @brief Method to send a chacon DIO command to a specific device.
 */
static int gChacon_set (struct ubus_context *aCtx, struct ubus_object *anObj,
		      			struct ubus_request_data *aReq, const char *aMethod,
		      			struct blob_attr *aMsg)
{
	struct blob_attr *theParams[__CHACON_MAX];
	uint32_t theSender;
	uint32_t theInterruptor;
	bool theState;

	/* Parse the Message */
	blobmsg_parse (set_chacon_policy, __CHACON_MAX, theParams, blob_data (aMsg), blob_len(aMsg));

	/* Sanity Checks. */
	if (!theParams[SET_SENDER] || !theParams[SET_INTERRUPTOR]|| !theParams[SET_STATE]) {

		printf ("Chacon Set Invalid arguments.\n");
		return UBUS_STATUS_INVALID_ARGUMENT;
	}

	/* Get Parameters. */
	theSender = blobmsg_get_u32 (theParams[SET_SENDER]);
	theInterruptor = blobmsg_get_u32 (theParams[SET_INTERRUPTOR]);
	theState = blobmsg_get_bool (theParams[SET_STATE]);


	return Chacon_SetInterruptorState (theSender, theInterruptor, theState);
}



/*!  ----------------------------------------------------------------------------
 *  @fn SetupUbus
 *
 *  @brief Setup the UBus Mechanism.
 */
int SetupUbus (void)
{
	uloop_init ();

	signal (SIGPIPE, SIG_IGN);

	gCtx = ubus_connect (NULL);

	if (!gCtx) {

		fprintf (stderr, "Failed to connect to ubus\n");
		return -1;
	}
	
	ubus_add_uloop (gCtx);

	return 0;
}


/*!  ----------------------------------------------------------------------------
 *  @fn UBusMain
 *
 *  @brief Main function of the UBus Loop.
 */
int UBusMain (void)
{
	int theRet;

	theRet = ubus_add_object (gCtx, &gChacon_object);
	
	if (theRet) {

		fprintf (stderr, "Failed to add object: %s\n", ubus_strerror (theRet));
	}

	uloop_run ();

	return 0;
}


/*!  ----------------------------------------------------------------------------
 *  @fn TerminateUBus
 *
 *  @brief This function terminate the Ubus mechanisme.
 */
int TerminateUBus (void)
{
	ubus_free (gCtx);
	uloop_done ();

	return 0;
}
