//===-- CommandObjectApropos.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "CommandObjectApropos.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"

#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"

using namespace lldb;
using namespace lldb_private;

//-------------------------------------------------------------------------
// CommandObjectApropos
//-------------------------------------------------------------------------

CommandObjectApropos::CommandObjectApropos (CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "apropos",
                         "Find a list of debugger commands related to a particular word/subject.",
                         NULL)
{
    CommandArgumentEntry arg;
    CommandArgumentData search_word_arg;

    // Define the first (and only) variant of this arg.
    search_word_arg.arg_type = eArgTypeSearchWord;
    search_word_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the argument entry.
    arg.push_back (search_word_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back (arg);
}

CommandObjectApropos::~CommandObjectApropos()
{
}


bool
CommandObjectApropos::DoExecute (Args& args, CommandReturnObject &result)
{
    const int argc = args.GetArgumentCount ();

    if (argc == 1)
    {
        const char *search_word = args.GetArgumentAtIndex(0);
        if ((search_word != NULL)
            && (strlen (search_word) > 0))
        {
            // The bulk of the work must be done inside the Command Interpreter, since the command dictionary
            // is private.
            StringList commands_found;
            StringList commands_help;
            m_interpreter.FindCommandsForApropos (search_word, commands_found, commands_help);
            if (commands_found.GetSize() == 0)
            {
                result.AppendMessageWithFormat ("No commands found pertaining to '%s'. Try 'help' to see a complete list of debugger commands.\n", search_word);
            }
            else
            {
                result.AppendMessageWithFormat ("The following commands may relate to '%s':\n", search_word);
                size_t max_len = 0;

                for (size_t i = 0; i < commands_found.GetSize(); ++i)
                {
                    size_t len = strlen (commands_found.GetStringAtIndex (i));
                    if (len > max_len)
                        max_len = len;
                }

                for (size_t i = 0; i < commands_found.GetSize(); ++i)
                    m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), 
                                                           commands_found.GetStringAtIndex(i),
                                                           "--",
                                                           commands_help.GetStringAtIndex(i),
                                                           max_len);
                
            }
            
            
            std::vector<const Property *> properties;
            const size_t num_properties = m_interpreter.GetDebugger().Apropos(search_word, properties);
            if (num_properties)
            {
                const bool dump_qualified_name = true;
                result.AppendMessageWithFormat ("\nThe following settings variables may relate to '%s': \n\n", search_word);
                for (size_t i=0; i<num_properties; ++i)
                    properties[i]->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name);

            }
            
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            result.AppendError ("'' is not a valid search word.\n");
            result.SetStatus (eReturnStatusFailed);
        }
    }
    else
    {
        result.AppendError ("'apropos' must be called with exactly one argument.\n");
        result.SetStatus (eReturnStatusFailed);
    }

    return result.Succeeded();
}
