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

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "CommandObjectApropos.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.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", "List debugger commands related to a word or subject.", nullptr)
{
    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() = default;

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

    if (argc == 1)
    {
        const char *search_word = args.GetArgumentAtIndex(0);
        if ((search_word != nullptr)
            && (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, true, true, true);
            
            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
            {
                if (commands_found.GetSize() > 0)
                {
                    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();
}
