#pragma once
#include "common.hpp"
#include <vector>


class Hooks {
    public:
        typedef void (*handler_t)();
        typedef enum {
            INIT,
            PRE_IO, POST_IO,
            PRE_CONFIG, POST_CONFIG,
            CACHE_CLEAN,
            DEINIT // must be last
        } hook_t;

        static void add(handler_t, hook_t, unsigned);
        static void run(hook_t);

    private:
        typedef std::vector<std::pair<unsigned, Hooks::handler_t> > handlers_t;
        static handlers_t hooks[];
};

#define HOOK_PRIO_EARLY 10
#define HOOK_PRIO_MID   50
#define HOOK_PRIO_LATE 100
#define HOOK_ADD(handler, hook, prio) UNUSED static const int CONCAT(hook_dummy_, __LINE__) = (Hooks::add(handler, Hooks::hook, prio), 1)
#define HOOK(hook, prio) static void CONCAT(hook_handler_dummy_, __LINE__)(); \
        HOOK_ADD(&CONCAT(hook_handler_dummy_, __LINE__), hook, prio); \
        static void CONCAT(hook_handler_dummy_, __LINE__)()