#ifndef TILE_BASE_STATUS_H
#define TILE_BASE_STATUS_H

#pragma once

#include "tile/base/internal/early_init.h"
#include "tile/base/internal/meta.h"
#include "tile/base/ref_ptr.h"

#include <memory>
#include <string>
#include <type_traits>

namespace tile {
class Status {
public:
    Status() noexcept = default;
    explicit Status(int status, const std::string &desc = internal::EarlyInitConstant<std::string>());

    template<typename T, typename = enable_if_t<std::is_same<underlying_type_t<T>, int>::value>>
    explicit Status(T status, const std::string &desc = internal::EarlyInitConstant<std::string>())
        : Status(static_cast<int>(status), desc)
    {}

    bool ok() const noexcept { return !state_; };

    int code() const noexcept { return !state_ ? 0 : state_->status; };

    const std::string &message() const noexcept;

    std::string ToString() const;

private:
    struct State : RefCounted<State> {
        int status;
        std::string desc;
    };

    RefPtr<State> state_;
};

std::ostream &operator<<(std::ostream &os, const Status &status);
}// namespace tile

#endif// TILE_BASE_STATUS_H
