/*
 * heartbeat.c 
 * com.apple.mobile.heartbeat service implementation.
 * 
 * Copyright (c) 2013 Martin Szulecki 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 
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <plist/plist.h>

#include "heartbeat.h"
#include "lockdown.h"
#include "common/debug.h"

/**
 * Convert a property_list_service_error_t value to a heartbeat_error_t value.
 * Used internally to get correct error codes.
 *
 * @param err An property_list_service_error_t error code
 *
 * @return A matching heartbeat_error_t error code,
 *     HEARTBEAT_E_UNKNOWN_ERROR otherwise.
 */
static heartbeat_error_t heartbeat_error(property_list_service_error_t err)
{
	switch (err) {
		case PROPERTY_LIST_SERVICE_E_SUCCESS:
			return HEARTBEAT_E_SUCCESS;
		case PROPERTY_LIST_SERVICE_E_INVALID_ARG:
			return HEARTBEAT_E_INVALID_ARG;
		case PROPERTY_LIST_SERVICE_E_PLIST_ERROR:
			return HEARTBEAT_E_PLIST_ERROR;
		case PROPERTY_LIST_SERVICE_E_MUX_ERROR:
			return HEARTBEAT_E_MUX_ERROR;
		case PROPERTY_LIST_SERVICE_E_SSL_ERROR:
			return HEARTBEAT_E_SSL_ERROR;
		default:
			break;
	}
	return HEARTBEAT_E_UNKNOWN_ERROR;
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t service, heartbeat_client_t * client)
{
	*client = NULL;

	if (!device || !service || service->port == 0 || !client || *client) {
		debug_info("Incorrect parameter passed to heartbeat_client_new.");
		return HEARTBEAT_E_INVALID_ARG;
	}

	debug_info("Creating heartbeat_client, port = %d.", service->port);

	property_list_service_client_t plclient = NULL;
	heartbeat_error_t ret = heartbeat_error(property_list_service_client_new(device, service, &plclient));
	if (ret != HEARTBEAT_E_SUCCESS) {
		debug_info("Creating a property list client failed. Error: %i", ret);
		return ret;
	}

	heartbeat_client_t client_loc = (heartbeat_client_t) malloc(sizeof(struct heartbeat_client_private));
	client_loc->parent = plclient;

	*client = client_loc;

	debug_info("heartbeat_client successfully created.");
	return 0;
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_client_start_service(idevice_t device, heartbeat_client_t * client, const char* label)
{
	heartbeat_error_t err = HEARTBEAT_E_UNKNOWN_ERROR;
	service_client_factory_start_service(device, HEARTBEAT_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(heartbeat_client_new), &err);
	return err;
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_client_free(heartbeat_client_t client)
{
	if (!client)
		return HEARTBEAT_E_INVALID_ARG;

	heartbeat_error_t err = heartbeat_error(property_list_service_client_free(client->parent));
	free(client);

	return err;
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_send(heartbeat_client_t client, plist_t plist)
{
	heartbeat_error_t res = HEARTBEAT_E_UNKNOWN_ERROR;

	res = heartbeat_error(property_list_service_send_binary_plist(client->parent, plist));
	if (res != HEARTBEAT_E_SUCCESS) {
		debug_info("Sending plist failed with error %d", res);
		return res;
	}

	debug_plist(plist);

	return res;
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_receive(heartbeat_client_t client, plist_t * plist)
{
	return heartbeat_receive_with_timeout(client, plist, 1000);
}

LIBIMOBILEDEVICE_API heartbeat_error_t heartbeat_receive_with_timeout(heartbeat_client_t client, plist_t * plist, uint32_t timeout_ms)
{
	heartbeat_error_t res = HEARTBEAT_E_UNKNOWN_ERROR;
	plist_t outplist = NULL;

	res = heartbeat_error(property_list_service_receive_plist_with_timeout(client->parent, &outplist, timeout_ms));
	if (res != HEARTBEAT_E_SUCCESS || !outplist) {
		debug_info("Could not receive plist, error %d", res);
		plist_free(outplist);
		return HEARTBEAT_E_MUX_ERROR;
	}

	*plist = outplist;

	debug_plist(*plist);

	return res;
}
