/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *
 *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <ctype.h>

#include "kazehakase.h"
#include "intl.h"
#include "utils/utils.h"
#include "glib-utils.h"
#include "estsearch.h"

#define ESTRAIER_URI "http://estraier.sourceforge.net/"
#define DTD   "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"
#define HEAD  "<head>\n" \
	      "  <title>Full-text search in history</title>\n" \
	      "  <style type=\"text/css\">\n" \
	      "  %s\n" \
              "  </style>\n" \
	      "</head>\n"
#define STYLE "body {\n" \
	      "background-color: #ccc;\n" \
	      "}\n" \
	      "h1 {\n" \
	      "text-align: center;\n" \
	      "font-size: 120%;\n" \
	      "}\n" \
	      "div.summary {\n" \
	      "padding: 0.2em;\n" \
	      "float: right;\n" \
	      "}\n" \
	      "div.content {\n" \
	      "background-color: #eee;\n" \
	      "margin: 1.2em;\n" \
	      "border-style: solid;\n" \
	      "border-color: black;\n" \
	      "border-width: 1px;\n" \
	      "}\n" \
	      "div.header {\n" \
	      "padding: 0.2em;\n" \
	      "background-color: #ccf;\n" \
	      "border-bottom: solid 1px black;\n" \
	      "margin: 0em;\n" \
	      "}\n" \
	      "span.title {\n" \
	      "font-weight: bold;\n"\
	      "}\n" \
	      "key {\n" \
	      "color: #ff0000;\n" \
	      "}\n" \
	      "img.thumbnail {\n" \
	      "width: 128px;\n" \
	      "float: left;\n" \
	      "margin: 0.2em;\n" \
	      "}\n" \
	      "div.footer {\n" \
	      "text-align: right;\n" \
	      "text-size: 90%;\n" \
	      "border-top: solid 1px #888;\n" \
	      "clear: both;\n" \
	      "}\n" 
#define HEADER  ""
#define CONTENT "<div class=\"content\">\n" \
	        "  <div class=\"header\"><span class=\"title\"><a href=\"%s\">%s</a></span></div>\n" \
		"    <div class=\"summary\"><img src=\"%s\" class=\"thumbnail\">\n" \
		"    <span class=\"sentence\">%s</span>\n" \
		"  </div>\n" \
		"  <div class=\"footer\">\n" \
		"    <span class=\"cache\"><a href=\"%s\">cache</a></span>\n" \
		"    <span class=\"date\">%s</span>\n" \
		"  </div>\n" \
		"</div>\n"
#define FOOTER  "<div class=\"footer\">\n" \
	        "Powered by <a href=\"%s\">Estraier</a> version %s\n" \
		"</div>\n"

static gboolean
execute_search_command(const gchar *search_text, gint *standard_output)
{
	gboolean ret;
	const gchar *estxview = "estxview ";
	gchar *command;
	gint argc;
	gchar **argv = NULL;
	GSpawnFlags flags;
	GPid pid;
	gint err;
	gchar **split = NULL;
	gchar *join = NULL;

	split = g_strsplit(search_text, "+", -1);
	if (split)
	{
		join = g_strjoinv(" ", split);
		g_strfreev(split);
	}

	command = g_strconcat(estxview,
			      "-max 20 ",
			      g_get_home_dir(), HISTORY_INDEX,
			      join,
			      NULL);
	if (join)
		g_free(join);

	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	flags = G_SPAWN_SEARCH_PATH; 
	ret = g_spawn_async_with_pipes(NULL,
				       argv,
				       NULL,
				       flags,
				       NULL,
				       NULL,
				       &pid,
				       NULL,
				       standard_output,
				       &err,
				       NULL);
	g_strfreev(argv);
	g_free(command);

	return ret;
}


static gchar *
create_search_result_html (gint out, const gchar *text)
{
	GIOChannel *io;
	gchar *line;
	gsize length;
	gchar *title = NULL, *uri = NULL, *date = NULL;
	gchar *cache_link = NULL;
	gchar *estversion = NULL;
	GString *desc = NULL, *html;

	io = g_io_channel_unix_new(out);
	g_io_channel_set_encoding(io, NULL, NULL);
	
	html = g_string_sized_new(0);

	g_string_append(html, DTD"\n");
	g_string_append(html, "<html>\n");
	g_string_append_printf(html, HEAD, STYLE); 
	g_string_append(html, "<body>\n");

	g_string_append_printf(html, "<h1>Search results for %s</h1>",
			       text);

	while (g_io_channel_read_line(io, &line, &length, NULL, NULL) == G_IO_STATUS_NORMAL)
	{
		if (!strncmp(line, "<document", 9))
		{
		}
		else if (!strncmp(line, "</document>", 11))
		{
			g_string_append_printf(html,
					       CONTENT,
					       uri,
					       title,
					       "no-image.png", /* thumbnail */
					       desc->str,
					       cache_link,
					       date);

			g_string_free(desc, TRUE);
			g_free(title);
			g_free(uri);
			g_free(date);
			g_free(cache_link);
		}
		else if (!strncmp(line, "<uri>", 5))
		{
			gchar *dirname, *orig_uri;
			gchar *link;
			size_t len;
			link = xml_get_content(line);
			cache_link = g_strconcat("file://",
						 link,
						 NULL);
			dirname = g_strconcat(g_get_home_dir(), 
					      HISTORY_DIR,
					      NULL);
			len = strlen(dirname);
			orig_uri = create_uri_from_filename(link + len);
			uri = url_decode(orig_uri);
			g_free(orig_uri);			
			g_free(dirname);
			g_free(link);
		}
		else if (!strncmp(line, "<title>", 7))
		{
			title = xml_get_content(line);
		}
		else if (!strncmp(line, "<date>", 6))
		{
			date = xml_get_content(line);
		}
		else if (!strncmp(line, "<text>", 6))
		{
			desc = g_string_sized_new(0);
		}
		else if (!strncmp(line, "<estxview", 9))
		{
			estversion = xml_get_attr(line, "version");
		}
		else if (!strncmp(line, "<summary", 8))
		{
			gchar *summary = xml_get_content(line);
			g_string_append(desc, summary);
			g_free(summary);
		}
		g_free(line);
	}
	g_io_channel_unref(io);
	g_string_append_printf(html, FOOTER, ESTRAIER_URI, estversion);
	g_string_append(html, "</body></html>");

	if (estversion)
		g_free(estversion);
	return g_string_free(html, FALSE);
}


gchar *
estsearch_get_search_result (const gchar *text)
{
	gint out;

	if (!text) return NULL;
	if (!exists_estindex) return NULL;

	if (!execute_search_command(text, &out))
		return NULL;

	return create_search_result_html(out, text);
}

gboolean
estsearch_update_index (gpointer data)
{
	const gchar *estindex = "estindex register -list - -hsuf \"*\" ";
	const gchar *estrelate = "estindex relate ";
	gchar *command;
	gchar *filename;
	gint in;
	gint argc;
	gchar **argv = NULL;
	GSpawnFlags flags;
	GPid pid;
	GIOChannel *io;

	command = g_strconcat(estindex, 
			      g_get_home_dir(), HISTORY_INDEX,
			      g_get_home_dir(), HISTORY_DIR,
			      NULL);

	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	flags = G_SPAWN_SEARCH_PATH |
		G_SPAWN_STDOUT_TO_DEV_NULL;
	g_spawn_async_with_pipes(NULL,
		      		 argv,
				 NULL,
		   		 flags,
		      		 NULL,
		      		 NULL,
		      		 &pid,
				 &in,
				 NULL,
				 NULL,
		      		 NULL);
	g_strfreev(argv);
	g_free(command);

	/* set filename to add index */
	filename = g_strconcat((gchar*)data, "\n", NULL); 	
	io = g_io_channel_unix_new(in);
	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_write_chars(io, filename, strlen(filename), NULL, NULL);
	g_io_channel_shutdown(io, TRUE, NULL);
	g_io_channel_unref(io);

	g_free(filename);
	g_free(data);
	
	flags = G_SPAWN_SEARCH_PATH |
		G_SPAWN_STDOUT_TO_DEV_NULL;
	
	/* score information process */
	command = g_strconcat(estrelate, 
			      g_get_home_dir(), HISTORY_INDEX,
			      NULL);

	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	g_spawn_async(NULL,
		      argv,
		      NULL,
		      flags,
		      NULL,
		      NULL,
		      &pid,
		      NULL);
	g_strfreev(argv);
	g_free(command);

	return FALSE;
}


gboolean
estsearch_purge_index (gpointer data)
{
	const gchar *estpurge = "estindex purge ";
	const gchar *estoptimize = "estindex optimize ";
	gchar *command;
	gint argc;
	gchar **argv = NULL;
	GSpawnFlags flags;
	GPid pid;

	command = g_strconcat(estpurge, 
			      g_get_home_dir(), HISTORY_INDEX,
			      NULL);

	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	flags = G_SPAWN_SEARCH_PATH |
		G_SPAWN_STDOUT_TO_DEV_NULL;
	g_spawn_async(NULL,
		      argv,
		      NULL,
		      flags,
		      NULL,
		      NULL,
		      &pid,
		      NULL);
	g_strfreev(argv);
	g_free(command);

	/* optimize index process */
	command = g_strconcat(estoptimize, 
			      g_get_home_dir(), HISTORY_INDEX,
			      NULL);

	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	g_spawn_async(NULL,
		      argv,
		      NULL,
		      flags,
		      NULL,
		      NULL,
		      &pid,
		      NULL);
	g_strfreev(argv);
	g_free(command);

	return FALSE;
}
