#pragma once

#include <memory>
#include "core/world/server_handle.hpp"
#include "./net/Server.hpp"
#include "./world/Serializer.hpp"
#include "./config.hpp"

namespace world::server {
    class Universe;
    class Elements;
}
class Server {
public:
    Server(config::server::options &);
    ~Server();

    void run();

    world::server_handle *getHandle() { return localHandle; }

private:
    /// Send-Receive packets
    //NOTE: triggers onPacket, onConnect & onDisconnect
    void pull();

    /// Handle networking requests
    bool onConnect(net::server::Peer*);
    bool onDisconnect(net::server::Peer*, bool, uint16_t);
    bool onPacket(net::server::Peer*, const memory::read_view&, net::PacketFlags);

    void broadcastMessage(const std::string &);
    void broadcastEntitiesChanges(world::server::Elements&);
    memory::read_buffer serializeEntitiesFrom(const world::server::Elements&, world::node_id root = generational::id());

    /// Handle local requests
    void onPacket(const world::action::packet &);

    void fillShape(const world::action::FillShape&);

    config::server::options& options;
    net::server::Server host;
    world::server::Serializer serializer;
    std::unique_ptr<world::server::Universe> universe;
    world::server_handle *localHandle;
};