#include "Application.h"
#include "Camera.h"
#include "Core/DateTime.h"
#include "Core/IoContext.h"
#include "Core/Logger.h"
#include "Core/Singleton.h"
#include "NngServer.h"
#include "RtspServer.h"
#include "Settings.h"
#include "VideoInput.h"
#include "WebRTC/Streamer.h"
#include "rw_mpp_api.h"
#include <boost/asio/signal_set.hpp>
#include <boost/scope/scope_exit.hpp>
#include <fstream>

int main(int argc, char const *argv[]) try {
    using namespace Core;
    using namespace Danki;
    LOG(info) << "app start...";
    int status = rw_mpp__init();
    if (status != 0) {
        LOG(error) << "rw_mpp__init() failed, status: " << status;
        return -1;
    }
    boost::scope::scope_exit raii([] {
        LOG(info) << "app exit.";
        rw_mpp__finalize();
    });

    auto application = Singleton<Application>::construct();
    auto settings = Singleton<Settings>::instance();

    auto camera = Singleton<Camera>::construct();
    auto rtsp = std::make_shared<RtspServer>(application->ioContext());
    auto streamer = std::make_shared<Streamer>(application->ioContext());
    streamer->start("127.0.0.1", 80);

    auto nng = Singleton<NngServer>::construct(application->ioContext());
    nng->start(settings->nngReplyPort());

    auto video = std::make_shared<VideoInput>(2592, 1536);
    video->setPacketHandler([&](const uint8_t *data, uint32_t size) {
        rtsp->push(data, size);
        streamer->push(data, size);
    });
    video->start();
    video->startEncode();
    boost::asio::signal_set signals(application->ioContext(), SIGINT);
    signals.async_wait([&](boost::system::error_code const &, int signal) {
        LOG(info) << "capture " << (signal == SIGINT ? "SIGINT" : "SIGTERM") << ",stop!";
        video.reset();
        rw_mpp__finalize();
        application->ioContext().stop();
    });
    return application->exec();
} catch (const boost::exception &e) {
    LOG(error) << "error";
} catch (const std::exception &e) {
    LOG(error) << e.what();
}
