#!/usr/local/bin/pike
#include <array.h>
#include <simulate.h>
#define MY_FILE_NAME "/~earendil/faerie/bin/search.cgi"

string *Environment;
mapping Query;
int Searching = 1, Case = 0;
string Search_text = "";

void horizontal_rule() { write("<hr>\n"); }

varargs void display_header(string entry) {
  string s;

  write("Content-type: text/html\n\n");
  s = read_bytes("HEAD");
  if( s ) {
    if( entry )
      s = replace(s, "WHAT", " (Dictionary entry, \""+replace(entry, "@", " ")+
	"\")");
    else if( Search_text && strlen(Search_text) )
      s = replace(s, "WHAT", " (\""+Search_text+"\")");
    else
      s = replace(s, "WHAT", "");
    write(s);
  }
  horizontal_rule();
}

void setup() {
  string s;
  object converter;

  s = getenv("QUERY_STRING");
  if( stringp(s) && strlen(s) ) {
    converter = clone((program) "convert.lpc");    
    Query = converter->convert_query_string(s);
  }
  if( !Query ) {
    Query = ([ ]);
    Searching = 0;
  }
  Search_text = Query["query"] || "";
  if( Query["case"] == "yes" )
    Case = 1;
}

void Query_display() {
  int i;
  string *v, a, b;
 
  write("<pre>\n");
  v = indices(Query);
  write(sprintf("%-22s %s\n", "Variable", "Value"));
  write(sprintf("%-22s %s\n", "--------", "-----"));
  for( i=0; i<sizeof(v); i++ )
    write(sprintf("%-22s %s\n", v[i], Query[v[i]]));
  write("----- Env Vars -----\n");
  for( i=0; i<sizeof(Environment); i++ ) {
    sscanf(Environment[i], "%s=%s", a, b);
    write(sprintf("%-22s %-56=s\n", a, b));
  }
  write("</pre>\n");
  horizontal_rule();
}

object make_searcher() {
  object o;
  o = clone((program) "lpc_search.cgi");
  if( Case )
    o->set_case_sensitive();
  switch( Query["type"] ) {
    case "and":   o->set_AND_search();   break;
    case "exact": o->set_EXACT_search(); break;
    case "or":
    default:      o->set_OR_search();    break;
  }
  if( Query["sort"] == "time" )
    o->set_time_sort();
  return o;
}

string short_time(int i) {
  string month, year, longdate;
  int day;
  
  longdate = ctime(i); 
  month = longdate[4..6];
  sscanf(longdate[8..9], "%d", day);
  year = longdate[22..23];
  return month + " " + day + ", '"+year;
}

void generate_web_entry(string file, int count, int date) {
  string site = "No Site", title = file;
  if( 2!=sscanf(read_bytes(file, 0, 160), "site=%s\ntitle=%s\n", site, title) )
    1;//return;
  write(sprintf(
	"<li> <a href=\"%s\">%s</a> (Score: %d)\n",
		site, title, count));
}

void generate_archive_entry(string file, int count, int date) {
  string title = "No Title", head = "";

  if( sscanf(file, "../story/%*s") )
    head = "Story: ";
  else if( sscanf(file, "../poems/%*s") )
    head = "Poem: ";

  sscanf(read_bytes(file, 0, 500), "%*s<title>%s</title>", title) 
    || sscanf(read_bytes(file, 0, 300), "<TITLE>%s</TITLE>", title);
  write(sprintf("<li> %s<a href=\"%s\">%s</a> (Score: %d) (%s)\n",
	head, file, title, count, short_time(date)));
}
  
void generate_dictionary_entry(string file, int count, int date) {
  string title;

  if( !sscanf(file, "../dictionary/%s.dict", file) )
    return; // Should not happen, but just in case...

  title = replace(file, "@", " ");
  write(sprintf("<li> Dictionary: <a href=\"%s\?%s\">%s</a> (Count: %d) (%s)\n",
	MY_FILE_NAME, file, title, count, short_time(date)));
}

int search_web() {
  string *files;
  mixed *results;
  int i;

  files = popen("echo ../WEB/*/*.txt") / " " - ({ });
  files[-1] = files[-1][0..strlen(files[-1])-2]; // strip off \n
  results = make_searcher()->search(Search_text, files);

  write("<font size=+1>\n");
  if( !sizeof(results) ) {
    write("No Internet Matches<p></font>\n");
    return 0;
  }
  write("Internet Matches:<p></font>\n");

  write("<ul>\n");
  for( i=0; i<sizeof(results); i++ )
    generate_web_entry(results[i][0], results[i][1], results[i][2]);
  write("</ul>\n");
  return sizeof(results);
}

int search_archive() {
  string *files;
  mixed *results;
  int i;

  files = popen("echo "+replace(read_bytes("Search-files"), "\n", " ")) / " ";
  files -= ({ "" });

  results = make_searcher()->search(Search_text, files);

  write("<font size=+1>\n");
  if( !sizeof(results) ) {
    write("No General Archive Matches<p></font>\n");
    return 0;
  }
  write("General Archive Matches:<p>\n</font>");

  write("<ul>\n");
  for( i=0; i<sizeof(results); i++ )
    generate_archive_entry(results[i][0], results[i][1], results[i][2]);
  write("</ul>\n");

  return sizeof(results);
}

int search_story() {
  string *files;
  mixed *results;
  int i;

  files = popen("echo ../story/*.html") / " " - ({ "" });

  results = make_searcher()->search(Search_text, files);

  write("<font size=+1>\n");
  if( !sizeof(results) ) {
    write("No Story Archive Matches<p></font>\n");
    return 0;
  }
  write("Story Archive Matches:<p></font>\n");

  write("<ul>\n");
  for( i=0; i<sizeof(results); i++ )
    generate_archive_entry(results[i][0], results[i][1], results[i][2]);
  write("</ul>\n");

  return sizeof(results);
}

int search_dictionary() {
  string *files;
  mixed *results;
  int i;

  files = popen("echo ../dictionary/*.dict") / " " - ({ "" });
  results = make_searcher()->search(Search_text, files);

  write("<font size=+1>\n");
  if( !sizeof(results) ) {
    write("No Dictionary Archive Matches<p></font>\n");
    return 0;
  }
  write("Dictionary Archive Matches:<p></font>\n");
  write("<ul>\n");
  for( i=0; i<sizeof(results); i++ )
    generate_dictionary_entry(results[i][0], results[i][1], results[i][2]);
  write("</ul>\n");

  return sizeof(results);
}

string redo_dict_entry(string s) {
  string href, title;
  title = replace(s, "@", " ");
  href = sprintf("<a href=%s?%s>%s</a>", MY_FILE_NAME, s, title);
  return href;
}

string redo_dict_line(string line) {
  string entry1, field, entry2;
  if( 3 == sscanf(line, "%s%[ ]%s", entry1, field, entry2) ) {
    sscanf(entry2, "%s%*[ ]", entry2);
    entry1 = redo_dict_entry(entry1);
    entry2 = redo_dict_entry(entry2);
    line = entry1 + field + entry2;
  } else
    line = redo_dict_entry(line);
  return line;
}

void display_dictionary() {
  string *files;
  string text, *lines;
  int i;

  files = get_dir("../dictionary/");
  files = map_array(files, 
	lambda(string s) { if( sscanf(s, "%s.dict", s) ) return s; }) - ({ 0 });
  files = sort_array(files, 
	lambda(string s, string t) { return lower_case(s) > lower_case(t); });
    
  write("<pre>\n");
  text = sprintf("%-78#s\n", files * "\n");
  lines = map_array(text / "\n", redo_dict_line);
  text = lines * "\n";
  write(text);
  write("</pre>\n");
}

void display_dictionary_entry(string entry) {
  string s, file, *allfiles;
  string a, b;
  int i;

  file = sprintf("../dictionary/%s.dict", entry);
  
  if( file_size(file) < 0 ) {
    write("Error: Entry \""+entry+"\" not found<p> Mail "+
     "<a href=mailto:earendil@bobcat.etsu.edu>Earendil</a><p>\n");
    return;
  }
  s = read_bytes(file, 0, 0x7fffffff);
  allfiles = map_array(get_dir("../dictionary/"),
	lambda(string s) { if( sscanf(s, "%s.dict", s) ) return s; }) - ({ 0 });
  allfiles -= ({ entry });
  for( i=0; i<sizeof(allfiles); i++ )
    if( 2 == sscanf(s, "%s "+replace(allfiles[i], "@", " ")+"%s", a, b) )
      s = a + " " + redo_dict_entry(allfiles[i])+b;
  write("<font size=+1>\n"+s+"\n</font>\n");
}

void main(int argc, string *argv, string *envp) {
  int count;

  Environment = envp;

  setup();
  //Query["database"] = "archive"; Search_text = "fairy";
  if( argc > 1 ) {
    Query = ([ ]);
    Search_text = "";
    display_header(argv[1]);
    argv[1] = replace(argv[1], "\\", "");
  } else
    display_header();

  clone((program) "select_form")->generate_form(Query);
/*
  write("If you encounter any problems with this program, "+
	"<a href=mailto:earendil@faeryland.tamu-commerce.edu>mail Earendil</a>, please.<br>\n"); */
  write("</ul>\n");

  horizontal_rule();
  if( Query["debug"] == "on" ) {
    Query_display(); // DEBUG
    write(sprintf("<pre>\nArgc: "+argc+"\nArgv: %O\n</pre>", argv));
  }
  if( argc > 1 ) {
    display_dictionary_entry(argv[1]);
  } else if( strlen(Search_text) ) {
    if( Query["database"] == "alldict" || Query["database"] == "all" ||
	Query["database"] == "archive" )
      count += search_dictionary();
    if( Query["database"] == "all" || Query["database"] == "archive" )
      count += search_archive();
    else if( Query["database"] == "story" )
      count += search_story();
    if( Query["database"] == "all" || Query["database"] == "web" )
      count += search_web();
    if( !count )
      write("<p><font size=+2>No Matches</font><p>\n");
    else
      write("<p><font size=+1>Total Matches: "+count+"</font><p>\n");
  } else 
    display_dictionary();
  write("<hr>\n");
  write("<a href="+MY_FILE_NAME+">Return to Main Dictionary</a><br>\n");
  write("<a href=../faerie.html>Return to Faerie Lore page</a><p>\n");

  write("\n</html></body>\n");
}
