#ifndef TILE_INIT_ON_INIT_H
#define TILE_INIT_ON_INIT_H

#pragma once

#include "tile/base/internal/macro.h"

#include <cstdint>
#include <functional>
#include <utility>

#define TILE_ON_INIT(...)                                                                                              \
    static ::tile::detail::OnInitRegistration TILE_INTERNAL_PP_CAT(tile_on_init_registration_object_, __COUNTER__)(    \
        __FILE__, __LINE__, __VA_ARGS__);

namespace tile {
namespace internal {
void SetAtExitCallback(std::function<void()> callback);

}
}// namespace tile

namespace tile {
namespace detail {

void RegisterOnInitCallback(std::int32_t priority, std::function<void()> init, std::function<void()> fini);

void RunAllInitializers();
void RunAllFinalizers();

class OnInitRegistration {
public:
    inline OnInitRegistration(const char *file,
                              std::uint32_t line,
                              std::function<void()> init,
                              std::function<void()> fini = nullptr)
        : OnInitRegistration(file, line, 0, init, fini)
    {}

    inline OnInitRegistration(const char *file,
                              std::uint32_t line,
                              std::int32_t priority,
                              std::function<void()> init,
                              std::function<void()> fini = nullptr)
    {
        RegisterOnInitCallback(priority, std::move(init), std::move(fini));
    }
};
}// namespace detail
}// namespace tile

#endif// TILE_INIT_ON_INIT_H
