/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * unity-webapps-runner.c
 * Copyright (C) Canonical LTD 2011
 *
 * Author: Robert Carr <racarr@canonical.com>
 *
unity-webapps 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 3 of the License, or
 * (at your option) any later version.
 *
 * unity-webapps 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 program.  If not, see <http://www.gnu.org/licenses/>.";
 */
#include <stdlib.h>
#include <stdio.h>

#include "unity-webapps-service.h"
#include "unity-webapps-context.h"
#include "../unity-webapps-desktop-infos.h"
#include "../unity-webapps-string-utils.h"
#include "unity-webapps-runner-amazon.h"

#include "config.h"


static UnityWebappsService *service = NULL;

static gchar *name = NULL;
static gchar *domain = NULL;
static gchar *homepage = NULL;
static gchar *app_id = NULL;
static gchar *url_patterns = NULL;
static gboolean amazon = FALSE;
static gboolean chromeless = TRUE;
static gboolean store_session_cookies = FALSE;
GMainLoop *loop = NULL;

static GOptionEntry option_entries[] =
	{
		{ "name", 'n',0,G_OPTION_ARG_STRING, &name, "Application name (base64 encoded)", NULL },
		{ "domain", 'd',0, G_OPTION_ARG_STRING, &domain, "Application domain", NULL},
		{ "amazon", 'a',0, G_OPTION_ARG_NONE, &amazon, "Launch amazon (with geoclue store selection)", NULL},
		{ "homepage", 'h',0, G_OPTION_ARG_STRING, &homepage, "Launch a webapp directly from its homepage", NULL},
		{ "app-id", 'i',0, G_OPTION_ARG_STRING, &app_id, "Launch a webapp with a specific APP_ID", NULL},
		{ "chrome", 'c',G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &chromeless, "Launch a webapp in default browser", NULL},
		{ "urlPatterns", 'u',0,G_OPTION_ARG_STRING, &url_patterns, "Add url coma separated patterns to the list that filters allowed urls for container navigation", NULL},
		{ "store-session-cookies", 's', 0, G_OPTION_ARG_NONE, &store_session_cookies, "Store the session cookies in the cookie jar", NULL},
        { NULL }
	};

gboolean
has_context (const gchar *name, const gchar *domain)
{
	gboolean res = FALSE;
	gchar** it;
	gchar** contexts = unity_webapps_service_list_contexts (service);

	for (it = contexts; it && *it; it++)
		{
			UnityWebappsContext *context =
				unity_webapps_context_new_for_context_name (service, *it);

			res = res || ((g_strcmp0 (unity_webapps_context_get_name (context), name) == 0)
						  && (g_strcmp0 (unity_webapps_context_get_domain (context), domain) == 0));

			g_object_unref (context);
		}

	return res;
}


static void
on_context_appeared (UnityWebappsService *service, const gchar *context_name, gpointer user_data)
{
	UnityWebappsContext *context = unity_webapps_context_new_for_context_name (service, context_name);

	if ((g_strcmp0 (unity_webapps_context_get_name (context), name) == 0)
		&& (g_strcmp0 (unity_webapps_context_get_domain (context), domain) == 0))
		{
			g_usleep (G_USEC_PER_SEC * 2);
			g_main_loop_quit (loop);
		}

	g_object_unref (context);
}

static void
open_webapp_with_legacy_chromeless (gchar * name,
									gchar * domain,
									gchar **files)
{
	gsize len;

	len = 0;
	g_base64_decode_inplace (name, &len);
	name[len] = 0;

	g_message("Launching webapp '%s' with the legacy container", name);

	gboolean has_files = files && files[0];
	if (has_files && !has_context (name, domain))
		{
			loop = g_main_loop_new (NULL, FALSE);
			unity_webapps_service_on_context_appeared (service,
													   on_context_appeared, NULL);

			unity_webapps_service_activate_application (service,
														name,
														domain,
														(const gchar * const*)files);

			g_main_loop_run (loop);

			unity_webapps_service_activate_application (service,
														name,
														domain,
														(const gchar * const*)files);
		}
	else
		{
			unity_webapps_service_activate_application (service,
														name,
														domain,
														(const gchar * const*)files);
		}
}

static gchar *
make_url_patterns_arg_for_container(const gchar * const url_patterns)
{
	gchar *url_patterns_args;
	gchar *default_no_arg;

	default_no_arg = g_strdup("");

	if ( ! url_patterns)
		return default_no_arg;

	url_patterns_args = g_strdup(url_patterns);
	g_strstrip(url_patterns_args);

	if (strlen(url_patterns_args) == 0)
		return default_no_arg;

	return g_strdup_printf("--webappUrlPatterns=%s", url_patterns);
}

static void
open_webapp_with_container_with_url(const gchar *url,
									const gchar *app_id)
{
	GError *error;

	g_return_if_fail(url != NULL);
	g_return_if_fail(app_id != NULL);

	gchar *url_pattern_args =
		make_url_patterns_arg_for_container(url_patterns);

	gchar *session_cookies_arg =
		store_session_cookies ?
		g_strdup("--store-session-cookies") : g_strdup("");

	gchar *command_line =
		g_strdup_printf(UNITY_WEBAPPS_CONTAINER_APP_NAME
						" --app-id='%s' --webapp --enable-back-forward %s %s %s",
						app_id, url_pattern_args, session_cookies_arg, url);
	g_free(url_pattern_args);
	g_free(session_cookies_arg);

	g_message("Launching webapp container for url '%s' and app_id '%s (command line '%s')",
			  url, app_id,
			  command_line);

	error = NULL;
	g_spawn_command_line_async(command_line, &error);

	if (error != NULL)
		{
			g_critical ("Error invoking browser: %s", error->message);
			g_error_free (error);
		}
}

/**
 *
 * \param name webapp name
 * \param domain domain name for the webapp
 */
static void
open_webapp_with_container(gchar * name,
						   gchar * domain,
						   gchar **files)
{
	gsize len;
	GError *error;
	gchar * desktop_id;
	gchar *decoded_name;

	g_return_if_fail(name != NULL);
	g_return_if_fail(domain != NULL);

	len = 0;
	decoded_name = g_base64_decode (name, &len);
	desktop_id =
		unity_webapps_desktop_infos_build_desktop_basename(decoded_name
														   , domain ? domain : "");

	gchar *url_pattern_args =
		make_url_patterns_arg_for_container(url_patterns);

	gchar *session_cookies_arg =
		store_session_cookies ?
		g_strdup("--store-session-cookies") : g_strdup("");

	gchar *command_line =
		g_strdup_printf(UNITY_WEBAPPS_CONTAINER_APP_NAME
						" --app-id='%s' --webapp='%s' --enable-back-forward %s %s",
						desktop_id,
						name,
						url_pattern_args,
						session_cookies_arg);
	g_free(session_cookies_arg);
	g_free(desktop_id);

	g_message("Launching webapp '%s' with the webapp container (command line '%s')",
			  decoded_name,
			  command_line);
	g_free(decoded_name);

	error = NULL;
	g_spawn_command_line_async(command_line, &error);

	if (error != NULL)
		{
			g_critical ("Error invoking browser: %s", error->message);
			g_error_free (error);
		}
}

gint
main (gint argc, gchar **argv)
{
	gint i;
	GOptionContext *context;
	GError *error;
	gchar *files[argc];
	error = NULL;

	context = g_option_context_new ("- Activate Unity WebApps");
	if (!context)
	  {
        g_error("Could not get proper option context");
        return 1;
	  }
	g_option_context_set_summary (context,
        "Launches a standalone webapp "
        "given a domain and a name (e.g."
		" \"unity-webapps-runner -n 'VHdpdHRlcgA='"
		" -d 'twitter.com'\").");

	// TODO: GETTEXT
	g_option_context_add_main_entries (context, option_entries, NULL);

	if (!g_option_context_parse (context, &argc, &argv, &error))
		{
			printf("Failed to parse arguments: %s\n", error->message);
			exit(1);
		}

	service = unity_webapps_service_new ();
	if (homepage != NULL)
		{
#if ! (defined(__ppc__) || defined(__ppc64__))
			open_webapp_with_container_with_url(homepage, app_id);
#else
			unity_webapps_service_open_homepage_sync (service, homepage);
#endif
			exit(0);
		}

	if (amazon == TRUE)
	  {
		gchar *country;
		const gchar *url;
		
		country = unity_webapps_runner_amazon_get_country ();

		url = unity_webapps_runner_amazon_get_homepage_for_country (country);
		if (NULL == url)
		  {
			g_error("Could not retrieve the url associated with the current country %s", country);
			return 1;
		  }
		g_free (country);

#if ! (defined(__ppc__) || defined(__ppc64__))
		open_webapp_with_container_with_url(url, app_id);
#else
		unity_webapps_service_open_homepage_sync (service, url);
#endif
		return 0;
	  }

	for (i = 1; i < argc; i++)
		files[i - 1] = argv[i];

	files[argc - 1] = NULL;

	if (!name || !domain)
		{
			gchar *help = g_option_context_get_help (context, TRUE, NULL);
			g_error("Invalid or missing 'domain' or 'name' fields:\n\n%s", help);
			g_free(help);
			return 1;
		}

#if ! (defined(__ppc__) || defined(__ppc64__))
	open_webapp_with_container(name, domain, &files[0]);
#else
	open_webapp_with_legacy_chromeless(name, domain, &files[0]);
#endif

  return 0;
}
