#include "core/node.h"

#include "core/simulator.h"
#include "core/error.h"

#include <optional>

namespace dofs {

Node::Node(Simulator *const sim, NodeId id, NodeType type) noexcept
        : _sim(sim), _id(id), _status(NodeStatus::OK), _type(type) {}

// Accessors
NodeId Node::id() const noexcept {
        return _id;
}
NodeStatus Node::status() const noexcept {
        return _status;
}
NodeType Node::type() const noexcept {
        return _type;
}

void Node::set_status(NodeStatus s) noexcept {
        _status = s;
}

static inline bool schedule_status_ok_after(Simulator *const sim, Time delay_ns,
                Node* self) {
        if (!sim) {
                log_error("ERROR", "Node: simulator instance not found for boot/reboot");
                return false;
        }

        sim->schedule_after(delay_ns, [self]() {
                self->set_status(NodeStatus::OK);
        });
        return true;
}

void Node::boot(Time boottime_ns) {
        if (_status != NodeStatus::DOWN) {
                log_error("ERROR", "boot() ignored: node not in DOWN state");
                return;
        }

        _status = NodeStatus::BOOTING;

        if (!schedule_status_ok_after(_sim, boottime_ns, this)) {
                // Intentionally left BOOTING; caller can handle recovery/logs.
        }
}

void Node::reboot(Time boottime_ns) {
        if (_status != NodeStatus::OK && _status != NodeStatus::THROTTLING) {
                log_error("ERROR", "reboot() ignored: node not in OK/THROTTLING state");
                return;
        }

        _status = NodeStatus::BOOTING;

        if (!schedule_status_ok_after(_sim, boottime_ns, this)) {
                // Intentionally left BOOTING; caller can handle recovery/logs.
        }
}

} // namespace dofs
