/*
 * idevicesetlocation.c
 * Simulate location on iOS device with mounted developer disk image
 *
 * Copyright (c) 2016-2020 Nikias Bassen, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; 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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>

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

#include <endianness.h>

#define DT_SIMULATELOCATION_SERVICE "com.apple.dt.simulatelocation"

enum {
	SET_LOCATION = 0,
	RESET_LOCATION = 1
};

static void print_usage(int argc, char **argv, int is_error)
{
	char *bname = strrchr(argv[0], '/');
	bname = (bname) ? bname + 1 : argv[0];

	fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] -- <LAT> <LONG>\n", bname);
	fprintf(is_error ? stderr : stdout, "       %s [OPTIONS] reset\n", bname);
	fprintf(is_error ? stderr : stdout, "\n" \
	  "OPTIONS:\n" \
	  "  -u, --udid UDID    target specific device by UDID\n" \
	  "  -n, --network      connect to network device even if available via USB\n" \
	  "  -h, --help         prints usage information\n" \
	  "  -d, --debug        enable communication debugging\n" \
	  "\n"
	  "Homepage: <" PACKAGE_URL ">\n"
	);
}

int main(int argc, char **argv)
{
	const struct option longopts[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "udid", required_argument, NULL, 'u' },
		{ "debug", no_argument, NULL, 'd' },
		{ "network", no_argument, NULL, 'n' },
		{ NULL, 0, NULL, 0}
	};
	uint32_t mode = 0;
	char *udid = NULL;
	enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK;

	int c = 0;
	while ((c = getopt_long(argc, argv, "dhu:n", longopts, NULL)) != -1) {
		switch (c) {
		case 'd':
			idevice_set_debug_level(1);
			break;
		case 'u':
			if (!*optarg) {
				fprintf(stderr, "ERROR: UDID must not be empty!\n");
				print_usage(argc, argv, 1);
				return 2;
			}
			free(udid);
			udid = strdup(optarg);
			break;
		case 'n':
			lookup_opts |= IDEVICE_LOOKUP_PREFER_NETWORK;
			break;
		case 'h':
			print_usage(argc, argv, 0);
			return 0;
		default:
			print_usage(argc, argv, 1);
			return 2;
		}
	}

	argc -= optind;
	argv += optind;

	if ((argc > 2) || (argc < 1)) {
		print_usage(argc+optind, argv-optind, 1);
		return -1;
	}

	if (argc == 2) {
		mode = SET_LOCATION;
	} else if (argc == 1) {
		if (strcmp(argv[0], "reset") == 0) {
			mode = RESET_LOCATION;
		} else {
			print_usage(argc+optind, argv-optind, 1);
			return -1;
		}
	}

	idevice_t device = NULL;

	if (idevice_new_with_options(&device, udid, lookup_opts) != IDEVICE_E_SUCCESS) {
		if (udid) {
			printf("ERROR: Device %s not found!\n", udid);
		} else {
			printf("ERROR: No device found!\n");
		}
		return -1;
	}

	lockdownd_client_t lockdown;
	lockdownd_client_new_with_handshake(device, &lockdown, NULL);

	lockdownd_service_descriptor_t svc = NULL;
	if (lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc) != LOCKDOWN_E_SUCCESS) {
		lockdownd_client_free(lockdown);
		idevice_free(device);
		printf("ERROR: Could not start the simulatelocation service. Make sure a developer disk image is mounted!\n");
		return -1;
	}
	lockdownd_client_free(lockdown);

	service_client_t service = NULL;

	service_error_t serr = service_client_new(device, svc, &service);

	lockdownd_service_descriptor_free(svc);

	if (serr != SERVICE_E_SUCCESS) {
		lockdownd_client_free(lockdown);
		idevice_free(device);
		printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr);
		return -1;
	}

	uint32_t l;
	uint32_t s = 0;

	l = htobe32(mode);
	service_send(service, (const char*)&l, 4, &s);
	if (mode == SET_LOCATION) {
		int len = 4 + strlen(argv[0]) + 4 + strlen(argv[1]);
		char *buf = malloc(len);
		uint32_t latlen;
		latlen = strlen(argv[0]);
		l = htobe32(latlen);
		memcpy(buf, &l, 4);
		memcpy(buf+4, argv[0], latlen);
		uint32_t longlen = strlen(argv[1]);
		l = htobe32(longlen);
		memcpy(buf+4+latlen, &l, 4);
		memcpy(buf+4+latlen+4, argv[1], longlen);

		s = 0;
		service_send(service, buf, len, &s);
	}
	
	idevice_free(device);

	return 0;
}
