/*!
  \file    DBMSrvCmd_Help.cpp
  \author  TiloH
  \ingroup DBMServer commands
  \brief   implementation of a class for the DBMServer command help

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2002-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


\endif
*/


//-----------------------------------------------------------------------------
// includes
//-----------------------------------------------------------------------------

#include <limits.h>

#include "SAPDB/DBM/Srv/DBMSrv_Reply.hpp"
#include "SAPDB/DBM/Srv/Commands/DBMSrvCmd_Help.hpp"
#include "SAPDB/DBM/Srv/ExplainHelp/DBMSrvExpHlp_SyntaxPart.hpp"
#include "hcn10.h"
#include "hcn36.h"
#include "hcn90.h"


//-----------------------------------------------------------------------------
// member of class DBMSrvCmd_Help
//-----------------------------------------------------------------------------

const char * DBMSrvCmd_Help::m_LongHelp=
    "@command help You request the list of all DBM commands. In addition, "
        "you receive a short syntax description for all commands."
    "@preconditions You do not need to log on to the Database Manager to execute this DBM command."
    "@syntax help [-obsolete] [<command>]"
    "@param -obsolete Specify the option -obsolete, to display exclusively the "
        "obsolete commands. The system displays a reference to the current name "
        "for each of these commands. If -obsolete is omitted, no obsolete DBM commands "
        "are displayed."
    "@param <command> A parameter restricting the list of displayed commands. Only those commands "
        "are displayed which start with the specified character string."
    "@reply OK<NL>"
        "<command_name> <description><NL>"
        "<command_name> <description><NL>"
        "..."
        "@replyvalue <command_name> The name of a DBM command."
        "@replyvalue <description> The syntax description of the command, if the option -obsolete is "
            "not used. Otherwise description contains a reference to the current name of the command. "
            "The description contains line breaks, if it is too long.";

DBMSrvCmd_Help::DBMSrvCmd_Help()
: DBMSrv_Command( DBMSrv_Command::KeyHelp, false, m_longHelp)
{
}

tcn00_Error DBMSrvCmd_Help::runCommand(VControlDataT * vcontrol,
                                       CommandT      * command,
                                       char          * replyData,
                                       int           * replyLen,
                                       int             replyLenMax)
{
    DBMSrv_Reply reply(replyData, replyLen, replyLenMax);
    DBMSrvCmd_Help commandObject;

    return commandObject.run(vcontrol, command, reply);
}

tcn00_Error DBMSrvCmd_Help::run(
    VControlDataT * vcontrol,
    CommandT      * command,
    DBMSrv_Reply  & reply)
{
    bool ShowObsolete=false;
    bool ShowAllCommands=true;
    bool CommandFound=false;

    size_t LineSize=80;

    const char * Command=0;
    const char * CommandEnd=0;

    const cn10DBMServerCommand * CommandInArray=DBMServerCommandsArray_cn10;

    reply.startWithOK();

    // analyze parameters
    cn90GetStartAndEndOfToken(command->args, Command, CommandEnd, 1);

    if(Command!=CommandEnd)
    {
        if(0==cn36_StrStrNUprCmp("-OBSOLETE", Command, CommandEnd-Command)) // we have a first parameter and it is a "-obsolete"
        {
            ShowObsolete=true;

            cn90GetStartAndEndOfToken(command->args, Command, CommandEnd, 2);

            if(Command!=CommandEnd)
                ShowAllCommands=false;
        }
        else
            ShowAllCommands=false;
    }

    //search the commands in the array of command information
    while(0!=CommandInArray->name)
    {
        if(ShowAllCommands || 0==strnicmp(Command, CommandInArray->name, CommandEnd-Command)) //the command matches by name
        {
            const char * Syntax=0;
            size_t       SyntaxLength=0;

            if(0!=CommandInArray->shortHelp)
            {
                Syntax=CommandInArray->shortHelp;
                SyntaxLength=cn36_TerminatingZeroOf(Syntax)-Syntax;
            }
            else
                if(0!=CommandInArray->longHelp)
                {
                    DBMSrvExpHlp_SyntaxPart SyntaxInfo(CommandInArray->longHelp); //search for first "@syntax" part of the command

                    if(SyntaxInfo.wasFound())
                    {
                        Syntax=SyntaxInfo.giveExplanationStart();
                        SyntaxLength=SyntaxInfo.giveExplanationLength();
                    }
                }

            if(0!=Syntax)
            {
                if((ShowObsolete && strlen(OBSOLETE_MARK_CN10)<=SyntaxLength && 0==strnicmp(OBSOLETE_MARK_CN10, Syntax, strlen(OBSOLETE_MARK_CN10))) ||    //if asked for obsolete functions, show obsolete functions only
                   (!ShowObsolete && (strlen(OBSOLETE_MARK_CN10)>SyntaxLength || 0!=strnicmp(OBSOLETE_MARK_CN10, Syntax, strlen(OBSOLETE_MARK_CN10)))) ||  //if asked for non obsolete functions, show non obsolete functions
                   (!ShowAllCommands && 0==cn36_StrStrNUprCmp(CommandInArray->name, Command, CommandEnd-Command))                                        ) //but always show exact matches
                {
                    if(0!=CommandInArray->shortHelp)
                    {
                        reply.appendStringWithMinWidth(CommandInArray->name, 25);
                        reply.appendLine(CommandInArray->shortHelp);
                    }
                    else
                        if(0!=CommandInArray->longHelp)
                        {
                            size_t LengthBeforeWrappedPart=strlen(CommandInArray->name);

                            if(LengthBeforeWrappedPart<25)
                                LengthBeforeWrappedPart=25;

                            reply.appendStringWithMinWidth(CommandInArray->name, 24);
                            reply.appendString(" ");
                            reply.appendIndentedWrappedLineN(Syntax, SyntaxLength, LengthBeforeWrappedPart, LineSize, LengthBeforeWrappedPart);
                        }
                }
            }
        }

        ++CommandInArray;
    }

    return OK_CN00;
}
