/****************************************************
 * help.c - /helpsys related routines               *
 ****************************************************
 * (C) PTlink Coders Team 2000 - Lamego@PTlink.net  *
 ****************************************************/

#include "config.h"
#include "m_commands.h"
#include "client.h"
#include "ircd.h"
#include "motd.h"
#include "msg.h"
#include "numeric.h"
#include "send.h"
#include "s_conf.h"
#include "s_log.h"
#include "conf_vars.h"
#include "help.h"
#include "irc_string.h" /* for strncpy_irc */

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

HelpItem        *user_help, *oper_help, *admin_help;

/*
 * m_functions execute protocol messages on this server:
 *
 *      cptr    is always NON-NULL, pointing to a *LOCAL* client
 *              structure (with an open socket connected!). This
 *              identifies the physical socket where the message
 *              originated (or which caused the m_function to be
 *              executed--some m_functions may call others...).
 *
 *      sptr    is the source of the message, defined by the
 *              prefix part of the message if present. If not
 *              or prefix not found, then sptr==cptr.
 *
 *              (!IsServer(cptr)) => (cptr == sptr), because
 *              prefixes are taken *only* from servers...
 *
 *              (IsServer(cptr))
 *                      (sptr == cptr) => the message didn't
 *                      have the prefix.
 *
 *                      (sptr != cptr && IsServer(sptr) means
 *                      the prefix specified servername. (?)
 *
 *                      (sptr != cptr && !IsServer(sptr) means
 *                      that message originated from a remote
 *                      user (not local).
 *
 *              combining
 *
 *              (!IsServer(sptr)) means that, sptr can safely
 *              taken as defining the target structure of the
 *              message in this server.
 *
 *      *Always* true (if 'parse' and others are working correct):
 *
 *      1)      sptr->from == cptr  (note: cptr->from == cptr)
 *
 *      2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
 *              *cannot* be a local connection, unless it's
 *              actually cptr!). [MyConnect(x) should probably
 *              be defined as (x == x->from) --msa ]
 *
 *      parc    number of variable parameter strings (if zero,
 *              parv is allowed to be NULL)
 *
 *      parv    a NULL terminated list of parameter pointers,
 *
 *                      parv[0], sender (prefix string), if not present
 *                              this points to an empty string.
 *                      parv[1]...parv[parc-1]
 *                              pointers to additional parameters
 *                      parv[parc] == NULL, *always*
 *
 *              note:   it is guaranteed that parv[0]..parv[parc-1] are all
 *                      non-NULL pointers.
 */

/*
 * m_helpsys	by Lamego (May 2000)
 *	parv[0] = sender prefix
 *	parv[1] = help topic
 */ 
int m_helpsys(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  char** ht;
  int found=0;
  
  if(	(ht=help_find(parc>1 ? parv[1] : "", user_help)) ) 
	{
	  found=1;
	  sendto_one(sptr, ":%s NOTICE %s :**************** \2USER HELP SYSTEM\2 ***************",
                  MENAME(sptr), sptr->name);        
		
	  while(*ht)
	    sendto_one(sptr, ":%s NOTICE %s :%s",
                   MENAME(sptr), sptr->name, *(ht++)); 
		   
	  sendto_one(sptr, ":%s NOTICE %s :*************************************************",
                   MENAME(sptr), sptr->name);
		   
	  if(HelpChan) 
	    sendto_one(sptr, ":%s NOTICE %s :For some human help please join %s", 
                MENAME(sptr), sptr->name, HelpChan);
    }
	
  if(IsAnOper(sptr) && (ht=help_find(parc>1 ? parv[1] : "",oper_help))) 
	{
	  found=1;    
	  sendto_one(sptr, ":%s NOTICE %s :**************** \2OPER HELP SYSTEM\2 ***************",
                MENAME(sptr), sptr->name);            
		
	  while(*ht)
		sendto_one(sptr, ":%s NOTICE %s :%s",
                        MENAME(sptr), sptr->name, *(ht++));
			  
	  sendto_one(sptr, ":%s NOTICE %s :*************************************************",
                   MENAME(sptr), sptr->name);                                           
    } 

  if(IsAdmin(sptr) && (ht=help_find(parc>1 ? parv[1] : "",admin_help))) 
    {
  	  found=1;
	  sendto_one(sptr, ":%s NOTICE %s :**************** \2ADMIN HELP SYSTEM\2 ***************",
                   MENAME(sptr), sptr->name);            
		   
	  while(*ht)
	    sendto_one(sptr, ":%s NOTICE %s :%s",
                   MENAME(sptr), sptr->name, *(ht++));
		   
	  sendto_one(sptr, ":%s NOTICE %s :*************************************************",
                   MENAME(sptr), sptr->name);        
		   
    }        
	
  if(!found)
	sendto_one(sptr, ":%s NOTICE %s :Help topic not found",
         MENAME(sptr), sptr->name);
		 
  return 0;	    
}

/******************************************
    Loads a help system from a text file
 ******************************************/
int help_load(char *fn, HelpItem **hi) {
    char *hl[1024]; /* buffer to store a full item */
    char line[256]; /* one line buffer */
    char topic[32]; /* current topic */
    char *tmp;
    int	 total;    /* total lines for the current item */
    FILE *helpfile;
    HelpItem *h,*last;   /* current,last help item */    
    *hi = NULL;
	
    if(!(helpfile = fopen(fn,"rt"))) 
	  {
	  	ircd_log(L_ERROR,"Could not open help file: %s",fn);
		return 1;
  	  }
	  
    h = (HelpItem *) malloc(sizeof(HelpItem));
    (*hi)=h;
    last=NULL;
    topic[0]='\0';
    total=0;
    while(fgets(line,sizeof(line),helpfile)) {
	if ((tmp = (char *) strchr(line, '\n')))
	    *tmp = '\0';
	if ((tmp = (char *) strchr(line, '\r')))
	    *tmp = '\0';	    
	if(line[0]=='*') {
	    if(total) {
		h->topic = strdup(topic);
		h->text = (char**) malloc(sizeof(char*) * (total+1));
		h->text[total]=NULL;	/* mark end of text*/
		while(total--) {
		    h->text[total] = strdup(hl[total]);
		};
		h->next = (HelpItem *) malloc(sizeof(HelpItem));
		last=h;
		h=h->next;
		total=0;
	    }
	    strncpy(topic,&line[1],sizeof(topic)); /* save topic*/
	} else 
	    hl[total++]=strdup(line);
    }
    free(h); /* Last help is *EOF ... lets discard it */
    last->next=NULL; /* mark end of list*/
    fclose(helpfile);
    return 0;
}

/******************************************
    Looks for a topic on help system
    returns help message or NULL (not found)
 ******************************************/
char** help_find(char* topic, HelpItem *hi) {
    HelpItem *h = hi;
    while(h) { 
	if(!strcasecmp(h->topic,topic)) 
	    return h->text;
	else    
	    h=h->next;
    }	    
    return NULL;
}

/***************************************************
    Fress all the memory alocated to an help item
 ***************************************************/
void help_free(HelpItem **hi) {
    char** ht; 
    HelpItem *h = *hi;
    HelpItem *tofree;
    while(h) {
	free(h->topic);
	ht=h->text;
	while(*ht) {
	    free(*(ht++));
	}
	free(h->text);
	tofree = h;
	h=h->next;
	MyFree(tofree);
    }
    (*hi)=NULL;
}
