/*
 * Copyright (c) 2013 Clément Bœsch
 *
 * 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 <quvi/quvi.h>

#include "libavformat/avformat.h"
#include "libavformat/internal.h"
#include "libavutil/avassert.h"
#include "libavutil/opt.h"

typedef struct {
    const AVClass *class;
    char *format;
    AVFormatContext *fmtctx;
} LibQuviContext;

#define OFFSET(x) offsetof(LibQuviContext, x)
#define FLAGS AV_OPT_FLAG_DECODING_PARAM
static const AVOption libquvi_options[] = {
    { "format", "request specific format", OFFSET(format), AV_OPT_TYPE_STRING, {.str="best"}, .flags = FLAGS },
    { NULL }
};

static const AVClass libquvi_context_class = {
    .class_name     = "libquvi",
    .item_name      = av_default_item_name,
    .option         = libquvi_options,
    .version        = LIBAVUTIL_VERSION_INT,
};

static int libquvi_close(AVFormatContext *s)
{
    LibQuviContext *qc = s->priv_data;
    if (qc->fmtctx)
        avformat_close_input(&qc->fmtctx);
    return 0;
}

static int libquvi_read_header(AVFormatContext *s)
{
    int i, ret;
    quvi_t q;
    quvi_media_t m;
    QUVIcode rc;
    LibQuviContext *qc = s->priv_data;
    char *media_url, *pagetitle;

    rc = quvi_init(&q);
    if (rc != QUVI_OK)
        goto quvi_fail;

    quvi_setopt(q, QUVIOPT_FORMAT, qc->format);

    rc = quvi_parse(q, s->filename, &m);
    if (rc != QUVI_OK)
        goto quvi_fail;

    rc = quvi_getprop(m, QUVIPROP_MEDIAURL, &media_url);
    if (rc != QUVI_OK)
        goto quvi_fail;

    if ((ret = ff_copy_whitelists(qc->fmtctx, s)) < 0)
        goto end;

    if (!qc->fmtctx->format_whitelist) {
        qc->fmtctx->format_whitelist = av_strdup("avi,asf,flv,mov,mpeg,mpegts,aac,h264,hevc,mp3,ogg,matroska,mxf,mp2");
        if (!qc->fmtctx->format_whitelist) {
            avformat_free_context(qc->fmtctx);
            qc->fmtctx = NULL;
            goto err_quvi_cleanup;
        }
    }
    if (strncmp(media_url, "http:", 5) && strncmp(media_url, "https:", 6)) {
        avformat_free_context(qc->fmtctx);
        qc->fmtctx = NULL;
        goto err_quvi_cleanup;
    }

    ret = avformat_open_input(&qc->fmtctx, media_url, NULL, NULL);
    if (ret < 0)
        goto end;

    rc = quvi_getprop(m, QUVIPROP_PAGETITLE, &pagetitle);
    if (rc == QUVI_OK)
        av_dict_set(&s->metadata, "title", pagetitle, 0);

    for (i = 0; i < qc->fmtctx->nb_streams; i++) {
        AVStream *st = avformat_new_stream(s, NULL);
        AVStream *ist = qc->fmtctx->streams[i];
        if (!st) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
        avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
        avcodec_copy_context(st->codec, qc->fmtctx->streams[i]->codec);
    }

    return 0;

quvi_fail:
    av_log(s, AV_LOG_ERROR, "%s\n", quvi_strerror(q, rc));
    ret = AVERROR_EXTERNAL;

end:
    quvi_parse_close(&m);
    quvi_close(&q);
    return ret;
}

static int libquvi_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    LibQuviContext *qc = s->priv_data;
    return av_read_frame(qc->fmtctx, pkt);
}

static int libquvi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{
    LibQuviContext *qc = s->priv_data;
    return av_seek_frame(qc->fmtctx, stream_index, timestamp, flags);
}

static int libquvi_probe(AVProbeData *p)
{
    int score;
    quvi_t q;
    QUVIcode rc;

    rc = quvi_init(&q);
    if (rc != QUVI_OK)
        return AVERROR(ENOMEM);
    score = quvi_supported(q, (char *)p->filename) == QUVI_OK ? AVPROBE_SCORE_EXTENSION : 0;
    quvi_close(&q);
    return score;
}

AVInputFormat ff_libquvi_demuxer = {
    .name           = "libquvi",
    .long_name      = NULL_IF_CONFIG_SMALL("libquvi demuxer"),
    .priv_data_size = sizeof(LibQuviContext),
    .read_probe     = libquvi_probe,
    .read_header    = libquvi_read_header,
    .read_packet    = libquvi_read_packet,
    .read_close     = libquvi_close,
    .read_seek      = libquvi_read_seek,
    .priv_class     = &libquvi_context_class,
    .flags          = AVFMT_NOFILE,
};
