/*!
 * Copyright (c) 2015-2018, 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: 04/05/2017
 */

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

#include "ubus-cpp/ubus-exec-receiver.h"

/*!  ----------------------------------------------------------------------------
 *  @fn handle_data_request
 *
 *  @brief callback called when data arrive.
 */
static void handle_data_request(struct ubus_request *a_req, int, struct blob_attr *a_msg)
{
	char *the_string;
	UBusExecReceiver *the_receiver = static_cast<UBusExecReceiver *>(a_req);
	//printf ("handle_data_request\n");

	the_string = blobmsg_format_json(a_msg, true);
	the_receiver->add_data(the_string);

	free(the_string);
}

/*!  ----------------------------------------------------------------------------
 *  @fn handle_complete_request
 *
 *  @brief callback called when the request is complete.
 */
static void handle_complete_request(struct ubus_request *a_req, int a_ret)
{
	UBusExecReceiver *the_receiver = static_cast<UBusExecReceiver *>(a_req);
	//printf ("handle_complete_request (%d)\n", a_ret);

	the_receiver->add_result(a_ret);
	the_receiver->complete();
}

/*!  ----------------------------------------------------------------------------
 *  @fn UBusExecReceiver
 *
 *  @brief Constructor of the Ubus Exec Receiver
 */
UBusExecReceiver::UBusExecReceiver(void)
{
	list = LIST_HEAD_INIT(list);

	pending = {0};
	status_code = 0;
	status_msg = 0;
	blocked = 0;
	cancelled = 0;
	notify = 0;

	peer = 0;
	seq = 0;

	raw_data_cb = NULL;
	data_cb = handle_data_request;
	fd_cb = NULL;
	complete_cb = handle_complete_request;

	ctx = NULL;
	priv = NULL;

	m_result = -1;
}

/*!  ----------------------------------------------------------------------------
 *  @fn ~UBusExecReceiver
 *
 *  @brief Destructor of the Ubus Exec Receiver
 */
UBusExecReceiver::~UBusExecReceiver(void)
{
}

/*!  ----------------------------------------------------------------------------
 *  @fn abort
 *
 *  @brief abort the current exec command.
 */
int UBusExecReceiver::abort(struct ubus_context *a_ctx)
{
	ubus_abort_request(a_ctx, this);

	return 0;
}

/*!  ----------------------------------------------------------------------------
 *  @fn complete_request_async
 *
 *  @brief launch the registered async request.
 */
int UBusExecReceiver::complete_request_async(struct ubus_context *a_ctx)
{
	data_cb = handle_data_request;
	complete_cb = handle_complete_request;

	ubus_complete_request_async(a_ctx, this);

	return 0;
}

/*!  ----------------------------------------------------------------------------
 *  @fn add_data
 *
 *  @brief add data from the receiver.
 */
void UBusExecReceiver::add_data(std::string a_data)
{
	m_data += a_data;
}

/*!  ----------------------------------------------------------------------------
 *  @fn get_data
 *
 *  @brief return the data received from the command.
 */
const std::string &UBusExecReceiver::get_data(void)
{
	return m_data;
}

/*!  ----------------------------------------------------------------------------
 *  @fn get_data
 *
 *  @brief save the result of the request.
 */
void UBusExecReceiver::add_result(int a_result)
{
	m_result = a_result;
}

/*!  ----------------------------------------------------------------------------
 *  @fn get_result
 *
 *  @brief return the result of the request.
 */
int UBusExecReceiver::get_result(void)
{
	return m_result;
}
