/* $Id: search.cpp,v 1.11 2004/01/02 04:05:37 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of the XFMail email client.                          *
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   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., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA.  *
 *                                                                             *
 *   Additional Permission granted:                                            *
 *                                                                             *
 *   This program is designed to use the XForms library, so we consider        *
 *   permission to link to that non-GPL-compatible library is implicit.        *
 *   However, in case this is not considered so, we explicitly state:          *
 *                                                                             *
 *   "As a special exception, the Archimedes Project, with the permission      *
 *    of all earlier copyright holders, formally gives permission to link      *
 *    this program with the XForms library, and distribute the resulting       *
 *    executable without the source code for XForms in the source              *
 *    distribution".                                                           *
 *                                                                             *
 ******************************************************************************/


#include <glib.h>

#include <fmail.h>
#include <umail.h>
#include <choose_folder.h>
#include <cfgfile.h>

extern cfgfile Config;

static FD_Find_Form *search_obj;
static int ready = 0;
static int sinprogress = 0;

#define MAX_SEARCH  127
typedef struct _search_res {
	char folder[MAX_FOLD_NAME_LEN];
	long uid;
}
search_res;

static struct _search_res *sresults = NULL;
static int rescount = 0;

void Search_Call(FL_OBJECT * obj, long param) {
}

void Search_Res_Call(FL_OBJECT * obj, long param) {
}

void Search_Dbl_Call(FL_OBJECT * obj, long param) {
	struct _mail_folder *folder;
	struct _mail_msg *msg;
	int num = fl_get_browser(search_obj->Search_Res);

	num--;
	if((sresults == NULL) || (num >= rescount))
		return;

	if((folder = get_folder_by_name(sresults[num].folder)) == NULL)
		return;

	if((msg = folder->getmsg(folder, sresults[num].uid)) == NULL)
		return;

	view_msg(msg, 1);

	return;
}

void Search_List_Call(FL_OBJECT * obj, long param) {
	fl_set_input(search_obj->Search_In,
				 fl_get_choice_text(search_obj->Search_List));
}

void search_init() {
	search_obj = create_form_Find_Form();

	fl_addto_choice(search_obj->Search_List, "Message");
	fl_addto_choice(search_obj->Search_List, "Header");
	fl_addto_choice(search_obj->Search_List, "Recipients");
	fl_addto_choice(search_obj->Search_List, "Body");
	fl_addto_choice(search_obj->Search_List, "Subject");
	fl_addto_choice(search_obj->Search_List, "From");
	fl_addto_choice(search_obj->Search_List, "To");
	fl_addto_choice(search_obj->Search_List, "Cc");
	fl_addto_choice(search_obj->Search_List, "Bcc");
	fl_addto_choice(search_obj->Search_List, "Sender");
	fl_addto_choice(search_obj->Search_List, "Flags");

	fl_set_button(search_obj->Search_Case, 0);
	fl_set_button(search_obj->Search_All, 0);
	fl_set_input(search_obj->Search_In, "Header");

	fl_set_browser_dblclick_callback(search_obj->Search_Res,
									 Search_Dbl_Call, 0);
	fl_clear_browser(search_obj->Search_Res);
	fl_set_browser_fontsize(search_obj->Search_Res,
							Config.getInt("FoldersFSize", FL_NORMAL_SIZE));
	fl_set_browser_fontstyle(search_obj->Search_Res,
							 Config.getInt("FoldersFStyle", FL_FIXEDBOLD_STYLE));
}

int close_search(FL_FORM * form, void *data) {
	if(search_obj && !sinprogress)
		fl_trigger_object(search_obj->Search_Close);

	return FL_IGNORE;
}

void search_free() {
	fl_free(search_obj);
}
	

void search_msgs() {
	int w, h;
	char geom[16];

	if(ready) {
		XRaiseWindow(fl_display, search_obj->Find_Form->window);
		return;
	}

	ready = 1;

	if(sresults)
		free(sresults);
	sresults = NULL;
	rescount = 0;

	Config.setFlags("searchgeom", CF_NOTCHANGED);
	w = 500;
	h = 330;
	sscanf(Config.get("searchgeom", "").c_str(), "%d %d", &w, &h);
	fl_clear_browser(search_obj->Search_Res);
	fl_set_form_minsize(search_obj->Find_Form, 500, 330);
	fl_set_form_maxsize(search_obj->Find_Form, 900, 600);
	fl_set_form_size(search_obj->Find_Form, w, h);
	fl_set_form_atclose(search_obj->Find_Form, close_search, NULL);
	fl_show_form(search_obj->Find_Form, FL_PLACE_FREE, FL_FULLBORDER,
				 "Search");
	fl_do_only_forms();

	sprintf(geom, "%d %d", search_obj->Find_Form->w,
			search_obj->Find_Form->h);
	Config.set("searchgeom", geom);
	fl_hide_form(search_obj->Find_Form);

	if(sresults)
		free(sresults);
	sresults = NULL;
	rescount = 0;

	ready = 0;
}

void search_call(struct _mail_folder *folder, long uid) {
	struct _mail_msg *msg;
	char buf[255];

	if(rescount >= MAX_SEARCH)
		return;

	if((msg = folder->getmsg(folder, uid)) == NULL)
		return;

	sresults[rescount].uid = uid;
	strcpy(sresults[rescount++].folder, get_folder_full_name(folder));

	snprintf(buf, sizeof(buf), "%-32.32s %-32.32s %s",
			 folder->name(folder),
			 msg->header->From ? msg->header->From->addr : "????",
			 msg->header->Subject ? msg->header->Subject : "????");

	fl_addto_browser(search_obj->Search_Res, buf);

	if(rescount >= MAX_SEARCH)
		display_msg(MSG_WARN, "search",
					"too many messages found\nnarrow your search criteria");
}

void Search_Sel_Call(FL_OBJECT * obj, long param) {
	select_found();
}

void Search_Run_Call(FL_OBJECT * obj, long param) {
	char exp[255], sin[255];
	int flags = 0;
	int sfold, efold;
	int nmsg, nfld, num;
	int i;

	if(sresults)
		free(sresults);
	sresults =
	(struct _search_res *) malloc(sizeof(struct _search_res) *
								  MAX_SEARCH);
	rescount = 0;

	if(sresults == NULL) {
		display_msg(MSG_FATAL, "search", "Malloc failed");
		return;
	}

	for(i = 0; i < MAX_SEARCH; i++) {
		sresults[i].uid = -1;
		*sresults[i].folder = '\0';
	}

	fl_clear_browser(search_obj->Search_Res);
	strncpy(exp, fl_get_input(search_obj->Search_Exp), 254);
	if(!exp || (strlen(exp) < 1)) {
		free(sresults);
		sresults = NULL;
		rescount = 0;
		return;
	}
	exp[254] = '\0';

	strncpy(sin, fl_get_input(search_obj->Search_In), 254);
	sin[254] = '\0';

	if(!fl_get_button(search_obj->Search_Case))
		flags |= S_CASE;

	nfld = nmsg = 0;
	if(fl_get_button(search_obj->Search_All)) {
		sfold = 0;
		efold = mailbox.size();
	} else {
		sfold = get_folder_index_noskip(current_folder);
		efold = sfold + 1;
	}

	set_cursor(main_form, XC_watch);
	set_cursor(search_obj->Find_Form, XC_watch);
	my_deactivate();
	sinprogress = 1;
	for(i = sfold; i < efold; i++) {
		if(abortpressed())
			break;

		if(mailbox[i] == NULL)
			continue;

		num = mailbox[i]->search(mailbox[i], exp, sin, flags, search_call);
		if(num == -1)
			break;

		if(num > 0) {
			nfld++;
			if(fl_get_button(search_obj->Search_Mark))
				mailbox[i]->status |= SEARCH;
			if((mailbox[i] == current_folder) && (sort_type == BY_FLAGS))
				current_folder->status &= ~SORTED;
		}

		nmsg += num;
	}

	my_activate();
	sinprogress = 0;
	set_cursor(main_form, 0);
	set_cursor(search_obj->Find_Form, 0);

	if((nmsg == 0) && (rescount == 0)) {
		display_msg(MSG_MSG, "search", "No messages found");
		display_msg(MSG_STAT, NULL, "");
	} else {
		display_msg(MSG_MSG, "search",
					"%d message(s) found in %d folder(s)",
					(nmsg == 0) ? rescount : nmsg, nfld);
		redraw_folders();
	}

	return;
}
