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

#ifndef liblldb_CommandObjectMultiword_h_
#define liblldb_CommandObjectMultiword_h_

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

namespace lldb_private {

//-------------------------------------------------------------------------
// CommandObjectMultiword
//-------------------------------------------------------------------------

class CommandObjectMultiword : public CommandObject
{
// These two want to iterate over the subcommand dictionary.
friend class CommandInterpreter;
friend class CommandObjectSyntax;
public:
    CommandObjectMultiword(CommandInterpreter &interpreter,
                           const char *name,
                           const char *help = nullptr,
                           const char *syntax = nullptr,
                           uint32_t flags = 0);
    
    ~CommandObjectMultiword() override;

    bool
    IsMultiwordObject() override
    {
        return true;
    }

    bool
    LoadSubCommand(const char *cmd_name,
                   const lldb::CommandObjectSP& command_obj) override;

    void
    GenerateHelpText(Stream &output_stream) override;

    lldb::CommandObjectSP
    GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override;

    CommandObject *
    GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override;

    void
    AproposAllSubCommands(const char *prefix,
                          const char *search_word,
                          StringList &commands_found,
                          StringList &commands_help) override;

    bool
    WantsRawCommandString() override
    {
        return false;
    }

    int
    HandleCompletion(Args &input,
                     int &cursor_index,
                     int &cursor_char_position,
                     int match_start_point,
                     int max_return_elements,
                     bool &word_complete,
                     StringList &matches) override;

    const char *
    GetRepeatCommand (Args &current_command_args, uint32_t index) override;

    bool
    Execute(const char *args_string,
            CommandReturnObject &result) override;
    
    bool
    IsRemovable() const override
    {
        return m_can_be_removed;
    }
    
    void
    SetRemovable (bool removable)
    {
        m_can_be_removed = removable;
    }
    
protected:

    CommandObject::CommandMap m_subcommand_dict;
    bool m_can_be_removed;
};
    
class CommandObjectProxy : public CommandObject
{
public:
    CommandObjectProxy(CommandInterpreter &interpreter,
                       const char *name,
                       const char *help = nullptr,
                       const char *syntax = nullptr,
                       uint32_t flags = 0);
    
    ~CommandObjectProxy() override;
    
    // Subclasses must provide a command object that will be transparently
    // used for this object.
    virtual CommandObject *
    GetProxyCommandObject() = 0;

    const char *
    GetHelpLong() override;
    
    bool
    IsRemovable() const override;

    bool
    IsMultiwordObject() override;
    
    void
    GenerateHelpText (Stream &result) override;
    
    lldb::CommandObjectSP
    GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override;
    
    CommandObject *
    GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override;
    
    void
    AproposAllSubCommands(const char *prefix,
                          const char *search_word,
                          StringList &commands_found,
                          StringList &commands_help) override;

    bool
    LoadSubCommand(const char *cmd_name,
                   const lldb::CommandObjectSP& command_obj) override;
    
    bool
    WantsRawCommandString() override;
    
    bool
    WantsCompletion() override;
    
    Options *
    GetOptions() override;

    int
    HandleCompletion(Args &input,
                     int &cursor_index,
                     int &cursor_char_position,
                     int match_start_point,
                     int max_return_elements,
                     bool &word_complete,
                     StringList &matches) override;

    int
    HandleArgumentCompletion(Args &input,
                             int &cursor_index,
                             int &cursor_char_position,
                             OptionElementVector &opt_element_vector,
                             int match_start_point,
                             int max_return_elements,
                             bool &word_complete,
                             StringList &matches) override;

    const char *
    GetRepeatCommand(Args &current_command_args,
                     uint32_t index) override;

    bool
    Execute(const char *args_string,
            CommandReturnObject &result) override;

protected:
    // These two want to iterate over the subcommand dictionary.
    friend class CommandInterpreter;
    friend class CommandObjectSyntax;
};

} // namespace lldb_private

#endif // liblldb_CommandObjectMultiword_h_
