/*
 * idevicenotificationproxy.c
 * Simple client for the notification_proxy service
 *
 * Copyright (c) 2009-2015 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

#define TOOL_NAME "idevicenotificationproxy"

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>

#ifdef WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#else
#include <unistd.h>
#endif

#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libimobiledevice/notification_proxy.h>

enum cmd_mode {
	CMD_NONE = 0,
	CMD_OBSERVE,
	CMD_POST
};

static int quit_flag = 0;

/**
 * signal handler function for cleaning up properly
 */
static void clean_exit(int sig)
{
	fprintf(stderr, "Exiting...\n");
	quit_flag++;
}

static void print_usage(int argc, char **argv)
{
	char *name = NULL;

	name = strrchr(argv[0], '/');
	printf("Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0]));
	printf("\n");
	printf("Post or observe notifications on a device.\n");
	printf("\n");
	printf("Where COMMAND is one of:\n");
	printf("  post ID [...]\t\tpost notification IDs to device and exit\n");
	printf("  observe ID [...]\tobserve notification IDs in the foreground until CTRL+C or signal is received\n");
	printf("\n");
	printf("The following OPTIONS are accepted:\n");
	printf("  -u, --udid UDID\ttarget specific device by UDID\n");
	printf("  -n, --network\t\tconnect to network device\n");
	printf("  -d, --debug\t\tenable communication debugging\n");
	printf("  -h, --help\t\tprints usage information\n");
	printf("  -v, --version\t\tprints version information\n");
	printf("\n");
	printf("Homepage:    <" PACKAGE_URL ">\n");
	printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n");
}

static void notify_cb(const char *notification, void *user_data)
{
	printf("> %s\n", notification);
}

int main(int argc, char *argv[])
{
	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
	lockdownd_service_descriptor_t service = NULL;
	lockdownd_client_t client = NULL;
	idevice_t device = NULL;
	np_client_t gnp = NULL;

	int result = -1;
	int i;
	const char* udid = NULL;
	int use_network = 0;
	int cmd = CMD_NONE;
	char* cmd_arg = NULL;

	int count = 0;
	char **nspec = NULL;
	char **nspectmp = NULL;

	signal(SIGINT, clean_exit);
	signal(SIGTERM, clean_exit);
#ifndef WIN32
	signal(SIGQUIT, clean_exit);
	signal(SIGPIPE, SIG_IGN);
#endif

	/* parse cmdline args */
	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
			idevice_set_debug_level(1);
			continue;
		}
		else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) {
			i++;
			if (!argv[i] || !*argv[i]) {
				print_usage(argc, argv);
				result = 0;
				goto cleanup;
			}
			udid = argv[i];
			continue;
		}
		else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
			print_usage(argc, argv);
			result = 0;
			goto cleanup;
		}
		else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) {
			use_network = 1;
			continue;
		}
		else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
			printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
			result = 0;
			goto cleanup;
		}
		else if (!strcmp(argv[i], "post") || !strcmp(argv[i], "observe")) {
			cmd = CMD_POST;
			if (!strcmp(argv[i], "observe")) {
				cmd = CMD_OBSERVE;
			}

			i++;

			if (!argv[i] || argv[i] == NULL || (!strncmp(argv[i], "-", 1))) {
				printf("Please supply a valid notification identifier.\n");
				print_usage(argc, argv);
				goto cleanup;
			}

			count = 0;
			nspec = malloc(sizeof(char*) * (count+1));

			while(1) {
				if (argv[i] && (strlen(argv[i]) >= 2) && (strncmp(argv[i], "-", 1) != 0)) {
					nspectmp = realloc(nspec, sizeof(char*) * (count+1));
					nspectmp[count] = strdup(argv[i]);
					nspec = nspectmp;
					count = count+1;
					i++;
				} else {
					i--;
					break;
				}
			}

			nspectmp = realloc(nspec, sizeof(char*) * (count+1));
			nspectmp[count] = NULL;
			nspec = nspectmp;
			continue;
		}
		else {
			print_usage(argc, argv);
			return 0;
		}
	}

	/* verify options */
	if (cmd == CMD_NONE) {
		print_usage(argc, argv);
		goto cleanup;
	}

	if (IDEVICE_E_SUCCESS != idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX)) {
		if (udid) {
			printf("No device found with udid %s.\n", udid);
		} else {
			printf("No device found.\n");
		}
		goto cleanup;
	}

	if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
		fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ret);
		goto cleanup;
	}

	ret = lockdownd_start_service(client, NP_SERVICE_NAME, &service);

	lockdownd_client_free(client);

	if ((ret == LOCKDOWN_E_SUCCESS) && (service->port > 0)) {
		if (np_client_new(device, service, &gnp) != NP_E_SUCCESS) {
			printf("Could not connect to notification_proxy!\n");
			result = -1;
		} else {
			np_set_notify_callback(gnp, notify_cb, NULL);

			switch (cmd) {
				case CMD_POST:
					i = 0;
					while(nspec[i] != NULL && i < (count+1)) {
						printf("< posting \"%s\"\n", nspec[i]);
						np_post_notification(gnp, nspec[i]);
						i++;
					}
					break;
				case CMD_OBSERVE:
				default:
					i = 0;
					while(nspec[i] != NULL && i < (count+1)) {
						printf("! observing \"%s\"\n", nspec[i]);
						np_observe_notification(gnp, nspec[i]);
						i++;
					}

					/* just sleep and wait for notifications */
					while (!quit_flag) {
						sleep(1);
					}

					break;
			}

			result = EXIT_SUCCESS;

			if (gnp) {
				np_client_free(gnp);
				gnp = NULL;
			}
		}
	} else {
		printf("ERROR: Could not start service %s: %s\n", NP_SERVICE_NAME, lockdownd_strerror(ret));
	}

	if (service) {
		lockdownd_service_descriptor_free(service);
		service = NULL;
	}

cleanup:
	if (nspec) {
		i = 0;
		while(nspec[i] != NULL && i < (count+1)) {
			free(nspec[i]);
			i++;
		}
		free(nspec);
	}

	if (cmd_arg) {
		free(cmd_arg);
	}

	if (device)
		idevice_free(device);

	return result;
}
