/*
 *
 *  Connection Manager
 *
 *  Copyright (C) 2007-2012  Intel Corporation. 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 version 2 as
 *  published by the Free Software Foundation.
 *
 *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

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

#include <gweb/gresolv.h>

#include "connman.h"

struct connman_wpad {
	struct connman_service *service;
	GResolv *resolv;
	char *hostname;
	char **addrlist;
};

static GHashTable *wpad_list = NULL;

static void resolv_debug(const char *str, void *data)
{
	connman_info("%s: %s\n", (const char *) data, str);
}

static void free_wpad(gpointer data)
{
        struct connman_wpad *wpad = data;

	g_resolv_unref(wpad->resolv);

	g_strfreev(wpad->addrlist);
	g_free(wpad->hostname);
	g_free(wpad);
}

static void download_pac(struct connman_wpad *wpad, const char *target)
{
}

static void wpad_result(GResolvResultStatus status,
					char **results, gpointer user_data)
{
	struct connman_wpad *wpad = user_data;
	const char *ptr;
	char *hostname;

	DBG("status %d", status);

	if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
		char *url;

		if (!results || g_strv_length(results) == 0)
			goto failed;

		url = g_strdup_printf("http://%s/wpad.dat", wpad->hostname);

		__connman_service_set_proxy_autoconfig(wpad->service, url);

		wpad->addrlist = g_strdupv(results);
		if (wpad->addrlist)
			download_pac(wpad, "wpad.dat");

		g_free(url);

		__connman_wispr_start(wpad->service,
					CONNMAN_IPCONFIG_TYPE_IPV4, CONNMAN_WISPR_SERVER_GOOGLE);

		return;
	}

	hostname = wpad->hostname;

	if (strlen(hostname) < 6)
		goto failed;

	ptr = strchr(hostname + 5, '.');
	if (!ptr || strlen(ptr) < 2)
		goto failed;

	if (!strchr(ptr + 1, '.'))
		goto failed;

	wpad->hostname = g_strdup_printf("wpad.%s", ptr + 1);
	g_free(hostname);

	DBG("hostname %s", wpad->hostname);

	g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
							wpad_result, wpad);

	return;

failed:
	connman_service_set_proxy_method(wpad->service,
				CONNMAN_SERVICE_PROXY_METHOD_DIRECT);

	__connman_wispr_start(wpad->service,
					CONNMAN_IPCONFIG_TYPE_IPV4, CONNMAN_WISPR_SERVER_GOOGLE);
}

int __connman_wpad_start(struct connman_service *service)
{
	struct connman_wpad *wpad;
	const char *domainname;
	char **nameservers;
	int index;
	int i;

	DBG("service %p", service);

	if (!wpad_list)
		return -EINVAL;

	index = __connman_service_get_index(service);
	if (index < 0)
		return -EINVAL;

	domainname = connman_service_get_domainname(service);
	if (!domainname)
		return -EINVAL;

	nameservers = connman_service_get_nameservers(service);
	if (!nameservers)
		return -EINVAL;

	wpad = g_try_new0(struct connman_wpad, 1);
	if (!wpad) {
		g_strfreev(nameservers);
		return -ENOMEM;
	}

	wpad->service = service;
	wpad->resolv = g_resolv_new(index);
	if (!wpad->resolv) {
		g_strfreev(nameservers);
		g_free(wpad);
		return -ENOMEM;
	}

	if (getenv("CONNMAN_RESOLV_DEBUG"))
		g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV");

	for (i = 0; nameservers[i]; i++)
		g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0);

	g_strfreev(nameservers);

	wpad->hostname = g_strdup_printf("wpad.%s", domainname);

	DBG("hostname %s", wpad->hostname);

	g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
							wpad_result, wpad);

	connman_service_ref(service);
	g_hash_table_replace(wpad_list, GINT_TO_POINTER(index), wpad);

	return 0;
}

void __connman_wpad_stop(struct connman_service *service)
{
	int index;

	DBG("service %p", service);

	if (!wpad_list)
		return;

	index = __connman_service_get_index(service);
	if (index < 0)
		return;

	if (g_hash_table_remove(wpad_list, GINT_TO_POINTER(index)))
		connman_service_unref(service);
}

int __connman_wpad_init(void)
{
	DBG("");

	wpad_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
							NULL, free_wpad);

	return 0;
}

void __connman_wpad_cleanup(void)
{
	DBG("");

	g_hash_table_destroy(wpad_list);
	wpad_list = NULL;
}
