#include "NngServer.h"
#include "Camera.h"
#include "Core/Logger.h"
#include "Nng/SocketAisoWrapper.h"
#include <boost/asio/io_context.hpp>
#include <boost/json/object.hpp>
#include <boost/json/parse.hpp>
#include <sstream>

NngServer::NngServer(boost::asio::io_context &ioContex) {
    m_socket = std::make_shared<Nng::Asio::Socket>(ioContex, Nng::Reply);
}

void NngServer::asyncRead() {
    m_socket->asyncReceive([ptr{weak_from_this()}](const boost::system::error_code &error, const Nng::Buffer &buffer) {
        if (error) {
            LOG(error) << error.message();
            return;
        }
        if (ptr.expired()) return;
        auto self = ptr.lock();
        std::error_code jsonError;
        auto value = boost::json::parse(buffer.data<char>(), jsonError);
        if (jsonError) {
            LOG(error) << jsonError.message();
        } else {
            auto &request = value.as_object();
            auto command = request.at("command").as_string();
            LOG(info) << "command: " << command;
            auto camera = Core::Singleton<Camera>::instance();
            if (command == "ZeroCheck") {

                camera->zeroCheck();
            } else if (command == "Zoom") {
                auto direction = request.at("direction").as_string();
                camera->zoom(direction == "In" ? Camera::Zoom::In : Camera::Zoom::Out);
            } else if (command == "Focus") {
                auto direction = request.at("direction").as_string();
                camera->focus(direction == "Far" ? Camera::Focus::Far : Camera::Focus::Near);
            }
        }

        LOG(info) << "nng received: " << buffer.data<char>();
        self->m_socket->send((void *)"world", strlen("world") + 1);
        self->asyncRead();
    });
}

void NngServer::start(uint16_t replyPort) {
    std::ostringstream oss;
    oss << "tcp://0.0.0.0:" << replyPort;
    m_socket->listen(oss.str());
    asyncRead();
}
