#ifndef INVOCATION_HPP
#define INVOCATION_HPP

#include "wrap-string.hpp"
#include "wrap-map.hpp"
#include "wrap-deque.hpp"

#include "streambuffer.hpp"


class InvocationData : public eng::map<eng::string, eng::string> {
public:
    const eng::string &get(const eng::string &key) const;
    
    void serialize(StreamBuffer *sb) const;
    void deserialize(StreamBuffer *sb);
};

class Invocation : public eng::nevernew {
public:
    enum Kind {
        KIND_INVALID,
        KIND_PLAN,
        KIND_LUA,
        KIND_FLUSH_PRINTS,
        KIND_TICK,
        KIND_LUA_SOURCE,
    };

private:
    Kind kind_;
    int64_t actor_;
    int64_t place_;
    eng::string action_;
    InvocationData data_;
public:
    Invocation();
    Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action, const InvocationData &data);
    Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action);
    
    bool valid() const { return kind_ != KIND_INVALID; }
    Kind kind() const { return kind_; }
    int64_t actor() const { return actor_; }
    int64_t place() const { return place_; }
    const eng::string &action() const { return action_; }
    const InvocationData &data() const { return data_; }

    void serialize(StreamBuffer *sb) const;
    void deserialize(StreamBuffer *sb);

    eng::string debug_string();
};

class InvocationQueue : public eng::deque<Invocation> {
};


#endif // INVOCATION_HPP
