/*
 * ZeroMQ Protocol
 * Copyright (c) 2019 Andriy Gelman
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <zmq.h>
#include "url.h"
#include "network.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "libavutil/time.h"

#define ZMQ_STRERROR zmq_strerror(zmq_errno())

typedef struct ZMQContext {
    const AVClass *class;
    void *context;
    void *socket;
    int   pkt_size;
    int   pkt_size_overflow; /*keep track of the largest packet during overflow*/
} ZMQContext;

#define OFFSET(x) offsetof(ZMQContext, x)
#define D AV_OPT_FLAG_DECODING_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
    { "pkt_size", "Maximum send/read packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 131072 }, -1, INT_MAX, .flags = D | E },
    { NULL }
};

static int zmq_proto_wait(URLContext *h, void *socket, int write)
{
    int ret;
    int ev = write ? ZMQ_POLLOUT : ZMQ_POLLIN;
    zmq_pollitem_t items = { .socket = socket, .fd = 0, .events = ev, .revents = 0 };
    ret = zmq_poll(&items, 1, POLLING_TIME);
    if (ret == -1) {
        av_log(h, AV_LOG_ERROR, "Error occured during zmq_poll(): %s\n", ZMQ_STRERROR);
        return AVERROR_EXTERNAL;
    }
    return items.revents & ev ? 0 : AVERROR(EAGAIN);
}

static int zmq_proto_wait_timeout(URLContext *h, void *socket, int write, int64_t timeout, AVIOInterruptCB *int_cb)
{
    int ret;
    int64_t wait_start = 0;

    while (1) {
        if (ff_check_interrupt(int_cb))
            return AVERROR_EXIT;
        ret = zmq_proto_wait(h, socket, write);
        if (ret != AVERROR(EAGAIN))
            return ret;
        if (timeout > 0) {
            if (!wait_start)
                wait_start = av_gettime_relative();
            else if (av_gettime_relative() - wait_start > timeout)
                return AVERROR(ETIMEDOUT);
        }
    }
}

static int zmq_proto_open(URLContext *h, const char *uri, int flags)
{
    int ret;
    ZMQContext *s        = h->priv_data;
    s->pkt_size_overflow = 0;
    h->is_streamed       = 1;

    if (s->pkt_size > 0)
        h->max_packet_size = s->pkt_size;

    s->context = zmq_ctx_new();
    if (!s->context) {
        /*errno not set on failure during zmq_ctx_new()*/
        av_log(h, AV_LOG_ERROR, "Error occured during zmq_ctx_new()\n");
        return AVERROR_EXTERNAL;
    }

    av_strstart(uri, "zmq:", &uri);

    /*publish during write*/
    if (h->flags & AVIO_FLAG_WRITE) {
        s->socket = zmq_socket(s->context, ZMQ_PUB);
        if (!s->socket) {
            av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR);
            goto fail_term;
        }

        ret = zmq_bind(s->socket, uri);
        if (ret == -1) {
            av_log(h, AV_LOG_ERROR, "Error occured during zmq_bind(): %s\n", ZMQ_STRERROR);
            goto fail_close;
        }
    }

    /*subscribe for read*/
    if (h->flags & AVIO_FLAG_READ) {
        s->socket = zmq_socket(s->context, ZMQ_SUB);
        if (!s->socket) {
            av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR);
            goto fail_term;
        }

        ret = zmq_setsockopt(s->socket, ZMQ_SUBSCRIBE, "", 0);
        if (ret == -1) {
            av_log(h, AV_LOG_ERROR, "Error occured during zmq_setsockopt(): %s\n", ZMQ_STRERROR);
            goto fail_close;
        }

        ret = zmq_connect(s->socket, uri);
        if (ret == -1) {
            av_log(h, AV_LOG_ERROR, "Error occured during zmq_connect(): %s\n", ZMQ_STRERROR);
            goto fail_close;
        }
    }
    return 0;

fail_close:
    zmq_close(s->socket);
fail_term:
    zmq_ctx_term(s->context);
    return AVERROR_EXTERNAL;
}

static int zmq_proto_write(URLContext *h, const unsigned char *buf, int size)
{
    int ret;
    ZMQContext *s = h->priv_data;

    ret = zmq_proto_wait_timeout(h, s->socket, 1, h->rw_timeout, &h->interrupt_callback);
    if (ret)
        return ret;
    ret = zmq_send(s->socket, buf, size, 0);
    if (ret == -1) {
        av_log(h, AV_LOG_ERROR, "Error occured during zmq_send(): %s\n", ZMQ_STRERROR);
        return AVERROR_EXTERNAL;
    }
    return ret; /*number of bytes sent*/
}

static int zmq_proto_read(URLContext *h, unsigned char *buf, int size)
{
    int ret;
    ZMQContext *s = h->priv_data;

    ret = zmq_proto_wait_timeout(h, s->socket, 0, h->rw_timeout, &h->interrupt_callback);
    if (ret)
        return ret;
    ret = zmq_recv(s->socket, buf, size, 0);
    if (ret == -1) {
        av_log(h, AV_LOG_ERROR, "Error occured during zmq_recv(): %s\n", ZMQ_STRERROR);
        return AVERROR_EXTERNAL;
    }
    if (ret > size) {
        s->pkt_size_overflow = FFMAX(s->pkt_size_overflow, ret);
        av_log(h, AV_LOG_WARNING, "Message exceeds available space in the buffer. Message will be truncated. Setting -pkt_size %d may resolve the issue.\n", s->pkt_size_overflow);
        ret = size;
    }
    return ret; /*number of bytes read*/
}

static int zmq_proto_close(URLContext *h)
{
    ZMQContext *s = h->priv_data;
    zmq_close(s->socket);
    zmq_ctx_term(s->context);
    return 0;
}

static const AVClass zmq_context_class = {
    .class_name = "zmq",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};

const URLProtocol ff_libzmq_protocol = {
    .name            = "zmq",
    .url_close       = zmq_proto_close,
    .url_open        = zmq_proto_open,
    .url_read        = zmq_proto_read,
    .url_write       = zmq_proto_write,
    .priv_data_size  = sizeof(ZMQContext),
    .priv_data_class = &zmq_context_class,
    .flags           = URL_PROTOCOL_FLAG_NETWORK,
};
