#ifndef COMMAND_H
#define COMMAND_H

#include <stdint.h>

class Command
{
public:
    enum : uint32_t
    {
        NOP,
        GO_FORWARD_UP_TO_CHAR,
        GO_FORWARD_ON_TO_CHAR,
        GO_BACK_UP_TO_CHAR,
        GO_BACK_ON_TO_CHAR,
        DELETE_MOTION,
        DELETE_LINE,
        DELETE_CHAR,
        DELETE_CHAR_BACK,
        CHANGE_MOTION,
        CHANGE_LINE,
        YANK_MOTION,
        YANK_LINE,
        UNDO,
        REDO,
        ENTER_INSERT_MODE,
        ENTER_INSERT_MODE_AFTER_CHAR,
        ENTER_INSERT_MODE_AFTER_LINE,
        ENTER_INSERT_MODE_START_OF_LINE,
        ENTER_INSERT_MODE_NEW_LINE_BEFORE,
        ENTER_INSERT_MODE_NEW_LINE_AFTER,
        PUT,
        PUT_BEFORE,
        CHANGE_CHAR,
        GO_TO_LINE,
        GO_TO_LAST_LINE,
        GO_LEFT,
        GO_DOWN,
        GO_UP,
        GO_RIGHT,
        GO_START_OF_LINE,
        GO_END_OF_LINE,
        NEXT,
        PREV,
        SCROLL_WINDOW_UP_ONE_LINE,
        SCROLL_WINDOW_DOWN_ONE_LINE,
        SCROLL_WINDOW_UP_HALF_SCREEN,
        SCROLL_WINDOW_DOWN_HALF_SCREEN,
        SCROLL_WINDOW_UP_WHOLE_SCREEN,
        SCROLL_WINDOW_DOWN_WHOLE_SCREEN,

        COMMAND_COUNT,
    };

    class Motion
    {
    public:
        enum : uint32_t
        {
            NOP,
            FORWARD_UP_TO_CHAR,
            FORWARD_ON_TO_CHAR,
            BACK_UP_TO_CHAR,
            BACK_ON_TO_CHAR,

            /* These motions aren't command-mode sequences but are used
             * internally. */
            THIS_LINE,

            MOTION_COUNT,
        };
    };

    struct Unit
    {
        uint32_t id;
        uint32_t count;
        uint32_t following_char;

        Unit()
        {
            id = 0u;
            count = 0u;
            following_char = 0u;
        }

        bool operator==(const Unit & other) const;
    };

    Unit main;
    Unit motion;

    bool operator==(const Command & other) const;
};

#endif
