/******************************************************************************
 Copyright (c) 2000-2001 Richard Woolcock

 Permission is hereby granted, free of charge, to any person obtaining a copy 
 of this software and associated documentation files (the "Software"), to deal 
 in the Software without restriction, including without limitation the rights 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 copies of the Software, and to permit persons to whom the Software is 
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all 
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 SOFTWARE.
 ******************************************************************************/

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

/******************************************************************************
 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");
   }
}