#ifndef COMMANDMAP_H
#define COMMANDMAP_H

#include <unordered_map>
#include <memory>
#include <list>
#include <vector>
#include "Command.h"

class CommandMap
{
public:
    enum : uint8_t
    {
        COMMAND_INVALID,
        COMMAND_INCOMPLETE,
        COMMAND_COMPLETE,
    };

    void add(const char * s, uint32_t id, std::shared_ptr<CommandMap> next_map,
            bool following_char);
    void add(const std::vector<uint32_t> & s, uint32_t id,
            std::shared_ptr<CommandMap> next_map, bool following_char);
    uint8_t lookup_command(const uint32_t * command_characters, size_t length,
            Command & command) const;

protected:
    struct Node
    {
        enum : uint8_t
        {
            FLAG_FOLLOWING_CHAR = 0x1u,
            FLAG_TERMINATOR     = 0x2u,
        };

        std::unordered_map<uint32_t, std::shared_ptr<Node>> next_chars;
        std::shared_ptr<CommandMap> next_map;
        uint32_t id;
        uint8_t flags;

        Node()
        {
            id = 0u;
            flags = 0u;
        }
    };

    Node m_root_node;

    uint8_t scan_units(
            std::list<Command::Unit> & units,
            const uint32_t * command_characters, size_t length,
            const Node * start_node) const;
};

#endif
