/* help.c */

#include "copyright.h"

/* commands for giving help */

#include <stdio.h>
#ifdef WANT_ANSI
#ifdef __STDC__
#include <stddef.h>
#include <unistd.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */
#include <string.h>
#include "mudconf.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
#include "help.h"

void spit_file(dbref player, const char *filename)
{
FILE	*f;
char	*buf, *fname, *p;

	fname = alloc_mbuf("spit_file.fname");
	strcpy(fname, FILEDIR);
	strcat(fname, filename);
	close(mudstate.reserved_fileid);
	if ((f = fopen(fname, "r")) == NULL) {
		notify(player, tprintf("Sorry, %s is unavailable.", fname));
		STARTLOG(LOG_PROBLEMS,"HLP","OPEN")
			buf = alloc_lbuf("spit_file.LOG.open");
			sprintf(buf, "Can't open %s for reading.", fname);
			log_text(buf);
			free_lbuf(buf);
		ENDLOG
	} else {
		buf = alloc_lbuf("spit_file.buf");
		while (fgets(buf, LBUF_SIZE - 1, f)) {
			for (p = buf; *p; p++)
				if (*p == '\n') {
					*p = '\0';
					break;
				}
			notify(player, buf);
		}
		fclose(f);
		free_lbuf(buf);
	}
	free_mbuf(fname);
	mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
}

/*
 * Cat file 'filename' to player 'destplayer'.  (If destplayer==NULL, cat the
 * file to 'player'.)
 */

void do_cat(dbref player, dbref cause, int key, char *filename, char *dest)
{
  dbref player2;

  if (dest && *dest) {
    player2 = lookup_player(player, dest, 1);
    if (player2 == NOTHING) {
      notify(player, "I couldn't find that player.");
      return;
    } else
      player = player2;
  }
  if (!strchr(filename, '/') && !strchr(filename, '\\'))
    spit_file(player, filename);
}

int helpindex_read (HASHTAB *htab, char *filename)
{
help_indx entry;
char	*p;
int	count;
FILE	*fp;

	hashflush(htab, 0);
	close(mudstate.reserved_fileid);
	if ((fp = fopen(filename, "r")) == NULL) {
		STARTLOG(LOG_PROBLEMS,"HLP","RDINDX")
			p = alloc_lbuf("helpindex_read.LOG");
			sprintf(p, "Can't open %s for reading.", filename);
			log_text(p);
			free_lbuf(p);
		ENDLOG
		mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
		return -1;
	}

	count = 0;
	while ((fread(&entry, sizeof(help_indx), 1, fp)) == 1) {

		/* Lowercase the entry and add all leftmost substrings.
		 * Substrings already added will be rejected by hashadd.
		 */

		for (p=entry.topic; *p; p++) *p = ToLower(*p);
		while (p>entry.topic) {
			p--;
			if (!isspace(*p))
				if ((hashadd(entry.topic, (int *)entry.pos, htab)) == 0)
					count++;
			*p = '\0';
		}
	}
	fclose(fp);
	mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
	hashreset(htab);
	return count;
}

void helpindex_load(dbref player)
{
int	news, help, whelp;
	news = helpindex_read(&mudstate.news_htab, mudconf.news_indx);
	help = helpindex_read(&mudstate.help_htab, mudconf.help_indx);
	whelp = helpindex_read(&mudstate.wizhelp_htab, mudconf.whelp_indx);
	if ((player != NOTHING) && !Quiet(player))
		notify(player,
			tprintf("Index entries: News...%d  Help...%d  Wizhelp...%d",
				news, help, whelp));
}

void helpindex_init()
{
	hashinit(&mudstate.news_htab, 17);
	hashinit(&mudstate.help_htab, 37);
	hashinit(&mudstate.wizhelp_htab, 37);
	helpindex_load(NOTHING);
}

void help_write(dbref player, char *topic, HASHTAB *htab, char *filename)
{
FILE	*fp;
char	*p, *line;
int	offset;

	if (*topic == '\0')
		topic = (char *) "help";
	else
		for (p=topic; *p; p++) *p = ToLower(*p);
	offset = (int)hashfind(topic, htab);
	if (offset <= 0) {
		notify(player, tprintf("No entry for '%s'.", topic));
		return;
	}
	close(mudstate.reserved_fileid);
	if ((fp = fopen(filename, "r")) == NULL) {
		notify(player,
			"Sorry, that function is temporarily unavailable.");
		STARTLOG(LOG_PROBLEMS,"HLP","OPEN")
			line = alloc_lbuf("help_write.LOG.open");
			sprintf(line, "Can't open %s for reading.", filename);
			log_text(line);
			free_lbuf(line);
		ENDLOG
		mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
		return;
	}
	if (fseek(fp, offset, 0) < 0L) {
		notify(player,
			"Sorry, that function is temporarily unavailable.");
		STARTLOG(LOG_PROBLEMS,"HLP","SEEK")
			line = alloc_lbuf("help_write.LOG.seek");
			sprintf(line, "Seek error in file %s.", filename);
			log_text(line);
			free_lbuf(line);
		ENDLOG
		fclose(fp);
		mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
		return;
	}
	line = alloc_lbuf("help_write");
	for (;;) {
		if (fgets(line, LBUF_SIZE - 1, fp) == NULL)
			break;
		if (line[0] == '&')
			break;
		for (p = line; *p != '\0'; p++)
			if (*p == '\n')
				*p = '\0';
		notify(player, line);
	}
	free_lbuf(line);
	fclose(fp);
	mudstate.reserved_fileid = open(DEV_NULL, O_RDWR, 0);
}

/* ---------------------------------------------------------------------------
 * do_help: display information from new-format news and help files
 */

void do_help(dbref player, dbref cause, int key, char *message)
{
char	*buf;
	switch (key) {
	case HELP_HELP:
		help_write(player, message, &mudstate.help_htab,
			mudconf.help_file);
		break;
	case HELP_NEWS:
		help_write(player, message, &mudstate.news_htab,
			mudconf.news_file);
		break;
	case HELP_WIZHELP:
		help_write(player, message, &mudstate.wizhelp_htab,
			mudconf.whelp_file);
		break;
	default:
		STARTLOG(LOG_BUGS,"BUG","HELP")
			buf = alloc_mbuf("do_help.LOG");
			sprintf(buf, "Unknown help file number: %d", key);
			log_text(buf);
			free_mbuf(buf);
		ENDLOG
	}
}