/******************************************************************************
 Copyright 2000-2001 Richard Woolcock.  All rights reserved.  This software may
 only be used, copied, modified, distributed or sub-licensed under the terms of
 the Glad license, which must always be included with any distributions of this
 software.  This copyright notice must remain unmodified at the top of any file
 containing any of the code found within this file.
 ******************************************************************************/

/******************************************************************************
 File Name        : help.c
 ******************************************************************************
 Description      : Help file system.
 ******************************************************************************
 Revision History :

 Date/Author : DD-MMM-YYYY   <author's name>
 Description : <description of change>

 Date/Author : 15-Jan-2001   Richard Woolcock (aka KaVir).
 Description : Initial version for Glad 2.0a.
 ******************************************************************************/

/******************************************************************************
 Required library files.
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sockets.h"
#include "glad.h"
#include "text_io.h"
#include "file_io.h"
#include "justify.h"
#include "string.h"
#include "soundex.h"
#include "help.h"

/******************************************************************************
 Required types.
 ******************************************************************************/

typedef struct
{
   char *   szKeyWord;
   char *   szFileName;
   status_t eStatus;
   bool     bJustify;
   char *   szHelpText;
} help_table_t;

/******************************************************************************
 Required local variables.
 ******************************************************************************/

/* Create the combat table */
static help_table_t s_stHelpTable[] =
{ /*  Keyword            File Name       Used by  Justify  */
   { "accept",          "accept",          ALL,    FALSE,  NULL },
   { "attack",          "attack",          ALL,    TRUE,   NULL },
   { "challenge",       "challenge",       ALL,    FALSE,  NULL },
   { "chat",            "chat",            ALL,    FALSE,  NULL },
   { "combat",          "combat",          ALL,    FALSE,  NULL },
   { "combat2",         "combatmore",      ALL,    FALSE,  NULL },
   { "commands",        "commands",        ALL,    FALSE,  NULL },
   { "create",          "create",          ALL,    FALSE,  NULL },
   { "defence",         "defence",         ALL,    TRUE,   NULL },
   { "damage",          "damage",          ALL,    TRUE,   NULL },
   { "dex",             "dex",             ALL,    FALSE,  NULL },
   { "dexterity",       "dexterity",       ALL,    TRUE,   NULL },
   { "emote",           "emote",           ALL,    FALSE,  NULL },
   { "eyes",            "eyes",            ALL,    FALSE,  NULL },
   { "feet",            "feet",            ALL,    FALSE,  NULL },
   { "feet2",           "feetcombo",       ALL,    FALSE,  NULL },
   { "glad",            "glad",            ALL,    FALSE,  NULL },
   { "hands",           "hands",           ALL,    FALSE,  NULL },
   { "hands2",          "handscombo",      ALL,    FALSE,  NULL },
   { "health",          "health",          ALL,    TRUE,   NULL },
   { "introduction",    "introduction",    ALL,    FALSE,  NULL },
   { "kavir",           "kavir",           ALL,    FALSE,  NULL },
   { "leave",           "leave",           ALL,    FALSE,  NULL },
   { "newbie",          "newbie",          ALL,    FALSE,  NULL },
   { "quit",            "quit",            ALL,    FALSE,  NULL },
   { "say",             "say",             ALL,    FALSE,  NULL },
   { "shutdown",        "shutdown",        ALL,    FALSE,  NULL },
   { "siz",             "siz",             ALL,    FALSE,  NULL },
   { "size",            "size",            ALL,    TRUE,   NULL },
   { "speed",           "speed",           ALL,    TRUE,   NULL },
   { "sta",             "sta",             ALL,    FALSE,  NULL },
   { "stamina",         "stamina",         ALL,    TRUE,   NULL },
   { "statistics",      "statistics",      ALL,    FALSE,  NULL },
   { "str",             "str",             ALL,    TRUE,   NULL },
   { "strength",        "strength",        ALL,    TRUE,   NULL },
   { "train",           "train",           ALL,    FALSE,  NULL },
   { "who",             "who",             ALL,    FALSE,  NULL },
   { "wit",             "wit",             ALL,    FALSE,  NULL },
   { "wits",            "wits",            ALL,    TRUE,   NULL },

   /* SYSTEM HELPFILES */
   { "@credits",        "credits",         ALL,    FALSE,  NULL },
   { "@score",          "score",           ALL,    FALSE,  NULL },
   { "@welcome",        "welcome",         ALL,    FALSE,  NULL },
   { NULL }
};

/******************************************************************************
 Global operations.
 ******************************************************************************/

/* Function: PutHelpText
 *
 * This function looks up a help file, formats it appropriate to the body and 
 * then displays the formatted text to the body.
 *
 * The function takes two parameters, as follows:
 *
 * pstConn:   The connection to which the help text should relate.
 * szKeyword: A pointer to a string containing the help keyword.
 *
 * This function has no return value.
 */
void PutHelpText( conn_t *pstConn, const char *szKeyWord )
{
   int   i;                       /* loop counter */
   char *szHelpText = NULL;       /* Help file name */
   char  szParsedHelpText [8192]; /* Parsed help file text */

   for ( i = 0; s_stHelpTable[i].szFileName != NULL; i++ )
   {
      if ( StringCompare( s_stHelpTable[i].szKeyWord, szKeyWord ) == CMP_EQUAL )
      {
         szHelpText = s_stHelpTable[i].szFileName;
         break;
      }
   }

   if ( szHelpText == NULL )
   {
      bool bFound = FALSE;

      PutOutput( pstConn, TO_USER, "No such helpfile as '%s'.\n\r", szKeyWord );
      PutOutput( pstConn, TO_USER, "Suggestions:", szKeyWord );

      for ( i = 0; s_stHelpTable[i].szFileName != NULL; i++ )
      {
         if ( s_stHelpTable[i].szKeyWord[0] == '@' )
         {
            continue; /* Ignore system helpfiles */
         }

         /* Check for similar sounding suggestions (at least 66% match) */
         if ( SoundexMatch( GetSoundexKey(s_stHelpTable[i].szKeyWord), 
            GetSoundexKey(szKeyWord) ) >= 66 )
         {
            bFound = TRUE;
            PutOutput( pstConn, TO_USER, " %s", s_stHelpTable[i].szKeyWord );
         }
      }

      if ( !bFound )
      {
         PutOutput( pstConn, TO_USER, " none.\n\r" );
      }
      else /* Similar sounding suggestions were found */
      {
         PutOutput( pstConn, TO_USER, ".\n\r" );
      }

      return;
   }

   if ( s_stHelpTable[i].szHelpText == NULL )
   {
      Log( "Loading helpfile '%s'.\n", szHelpText );
      s_stHelpTable[i].szHelpText = LoadHelp( szHelpText );
   }

   if ( s_stHelpTable[i].szHelpText == NULL )
   {
      Log( "Unable to load helpfile '%s'.\n", szHelpText );
      PutOutput( pstConn, TO_USER, "Sorry, that help file is missing.\n\r" );
   }
   else /* Help file was successfully loaded */
   {
      char *szOutText;
      body_t *pstBody = pstConn->pstBody;

      /* See if they have a body */
      if ( pstBody == NULL )
      {
         /* If they don't have a body, use an empty structure */
         static body_t s_stDummyBody;
         pstBody = &s_stDummyBody;
      }

      /* Parse the help text */
      TextParse( pstBody, s_stHelpTable[i].szHelpText, szParsedHelpText );

      if ( s_stHelpTable[i].bJustify == TRUE )
      {
         /* Justify the text if appropriate for the help file */
         szOutText = Justify(szParsedHelpText, 79, JUSTIFY_LEFT);
      }
      else /* s_stHelpTable[i].bJustify == FALSE */
      {
         /* Don't justify the text */
         szOutText = szParsedHelpText;
      }

      /* Display the help file to the connection */
      PutOutput( pstConn, TO_USER, "%s\n\r", szOutText );
   }
}



/* Function: DisplayHelpIndex
 *
 * This function displays the help index, listing all of the available topics.
 *
 * The function takes one parameter, as follows:
 *
 * pstConn: The connection to which the index should be displayed.
 *
 * This function has no return value.
 */
void DisplayHelpIndex( conn_t *pstConn )
{
   int i;          /* Loop counter */
   int iCount = 0; /* Number of help topics printed on the line */

   /* Loop through all the topics in the helpfile table */
   for ( i = 0; s_stHelpTable[i].szFileName != NULL; i++ )
   {
      if ( s_stHelpTable[i].szKeyWord[0] == '@' )
      {
         continue; /* Ignore system helpfiles */
      }

      /* Display the help keyword if the connection has access to it */
      if ( ( GetStatus(pstConn) & s_stHelpTable[i].eStatus ) != 0 )
      {
         PutOutput(pstConn,TO_USER,"%-19s%s",s_stHelpTable[i].szKeyWord,
            (!(++iCount%4))?"\n\r":"");
      }
   }

   /* Add an extra newline if necessary, for formatting purposes */
   if ( (iCount % 4) != 0 )
   {
      PutOutput(pstConn,TO_USER,"\n\r");
   }
}