#include "savestream.h"

SaveStream::SaveStream(QObject *parent) : QObject{parent} {}

bool SaveStream::init(AVFormatContext *formatContext,
                      AVPacketQueueManager *queueManager, int videoIndex) {
    // m_inputCodecContex = codecContex;
    m_inputFormatContext = formatContext;
    // m_saverQueue = queue;
    m_queueManager = queueManager;
    m_videoIndex = videoIndex;
    m_start = openFile();
    if (!m_start) {
        free();
    }
    return m_start;
}

void SaveStream::setSaveFileDirPath(QString fileDirPath) {
    m_outputDirPath = fileDirPath;
}

void SaveStream::close() {
    // QMutexLocker locker(&m_mutex);
    m_start = false;
}

void SaveStream::startSaveStream() {
    qDebug() << "SaveStreamThreadID:" << QThread::currentThreadId();
    if (!m_start) {
        return;
    }
    int frameIndex = 0;
    int64_t dts = 0;
    int64_t dts_last = 0;
    int64_t first_pts = 0;
    int64_t last_pts = 0;
    while (m_start || !m_queueManager->isEmptySaveQueue()) {
        if (m_queueManager->isEmptySaveQueue()) {
            QThread::usleep(1000);
            continue;
        }
        AVPacket *inputPacket = m_queueManager->dequeueSavePacket();
        if (isValidAVPacket(inputPacket)) {
            AVStream *in_stream =
                m_inputFormatContext->streams[inputPacket->stream_index];
            AVStream *out_stream = m_formatContextSave->streams[0];
            if (inputPacket->pts == AV_NOPTS_VALUE) {
                // 两帧之间的时长us
                int interval =
                    (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);
                inputPacket->pts =
                    (double)(frameIndex * interval) /
                    (double)(av_q2d(in_stream->time_base) * AV_TIME_BASE);
                inputPacket->dts = inputPacket->pts;
                // 两帧之间的间隔时间
                inputPacket->duration =
                    (double)interval /
                    (double)(av_q2d(in_stream->time_base) * AV_TIME_BASE);
            }

            av_packet_rescale_ts(inputPacket, in_stream->time_base,
                                 out_stream->time_base);
            // 由于保存的m_formatContextSave只创建了一个视频流，而读取到的图像的流索引不一定为0，可能会出现错误【Invalid
            // packet stream index: 1】
            // 所以这里需要将stream_index指定为和m_formatContextSave中视频流索引相同，因为就一个流，所以直接设置为0
            inputPacket->stream_index = 0;
            inputPacket->pos = -1;
            dts = inputPacket->dts;
            // if (dts < dts_last) {
            //     av_packet_unref(inputPacket);
            //     continue;
            // }
            // dts_last = dts;

            if (first_pts == 0) first_pts = inputPacket->pts;
            last_pts = inputPacket->pts;

            int ret = av_interleaved_write_frame(
                m_formatContextSave,
                inputPacket);  // 将数据包写入输出媒体文件
            if (ret < 0) {
                qDebug() << "save packet error!";
            } else {
            }

            // av_packet_unref(inputPacket);
            inputPacket = nullptr;
            frameIndex++;
        } else {
            QThread::usleep(1000);
        }
    }

    // AVStream *out_stream = m_formatContextSave->streams[0];
    // out_stream->start_time = 0;
    // m_formatContextSave->start_time = 0;
    // int64_t duration_pts = last_pts - first_pts;
    // // duration_pts = av_rescale(duration_pts, 1, AV_TIME_BASE);
    // m_formatContextSave->duration = duration_pts;

    // AVStream *stream = m_formatContextSave->streams[0];
    // stream->duration = duration_pts;

    // 写入文件尾
    if (m_formatContextSave && m_writeHeader) {
        av_write_trailer(m_formatContextSave);
        // if (m_formatContextSave->duration == 0) {
        //     m_formatContextSave->duration =
        //         (m_lastPts - m_firstPts) *
        //         av_q2d(m_formatContextSave->streams[0]->time_base);
        // }
        m_writeHeader = false;
    }

    free();
    qDebug() << "视频保存结束！";
    emit sendErrorMessageSignal("视频保存结束!", 1);
}

bool SaveStream::openFile() {
    // QMutexLocker locker(&m_mutex);
    QDir dir;
    if (!dir.exists(m_outputDirPath)) {
        dir.mkdir(m_outputDirPath);
    }
    QString strName = QString("/%1.ts").arg(
        QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss"));
    strName = m_outputDirPath + strName;
    // const AVOutputFormat *ofmt = av_guess_format("mp4", NULL, NULL);
    int ret = avformat_alloc_output_context2(
        &m_formatContextSave, nullptr, nullptr, strName.toStdString().data());
    if (ret < 0) {
        showError(ret);
        qWarning() << "avformat_alloc_output_context2 Error!";
        free();
        return false;
    }

    // 向媒体文件添加新流
    m_videoStreamOut = avformat_new_stream(m_formatContextSave, nullptr);
    if (!m_videoStreamOut) {
        free();
        qWarning() << "Create New Stream Error";
        return false;
    }

    // 拷贝一些参数，给codecpar赋值(这里使用编码器上下文进行赋值)
    ret = avcodec_parameters_copy(
        m_videoStreamOut->codecpar,
        m_inputFormatContext->streams[m_videoIndex]->codecpar);
    if (ret < 0) {
        showError(ret);
        free();
        qWarning() << "avcodec_parameters_from_context Failed";
        return false;
    }
    m_videoStreamOut->codecpar->codec_tag = 0;

    av_dump_format(m_formatContextSave, 0, strName.toStdString().data(), 1);
    if (!(m_formatContextSave->flags & AVFMT_NOFILE)) {
        // 创建并初始化AVIOContext以访问url所指示的资源。
        ret = avio_open(&m_formatContextSave->pb, strName.toStdString().data(),
                        AVIO_FLAG_WRITE);
        if (ret < 0) {
            showError(ret);
            qWarning() << "Open file Error";
            free();
            return false;
        }
    }

    // 写入文件头
    ret = avformat_write_header(m_formatContextSave, nullptr);
    if (ret < 0) {
        showError(ret);
        free();
        qWarning() << "avformat_write_header Error";
        return false;
    }

    m_writeHeader = true;
    qDebug() << "保存视频文件初始化成功！";
    return true;
}

void SaveStream::free() {
    // 关闭文件
    if (m_formatContextSave && !(m_formatContextSave->flags & AVFMT_NOFILE)) {
        avio_close(m_formatContextSave->pb);
        // av_freep(m_videoStreamOut);

        // avformat_free_context(m_formatContextSave);
        // m_formatContextSave = nullptr;
    }
    if (m_formatContextSave) {
        avformat_free_context(m_formatContextSave);
        m_formatContextSave = nullptr;
    }
}

bool SaveStream::isValidAVPacket(AVPacket *pkt) {
    if (pkt == nullptr) {
        qDebug() << "SaveStream: Invalid AVPacket 0: packet pointer is null.";
        return false;
    }
    // 检查数据指针和大小
    if (pkt->data == nullptr || pkt->size <= 0) {
        qDebug() << "SaveStream: Invalid AVPacket 0: data is null or size is "
                    "non-positive.\n";
        return false;
    }

    // 检查时间戳
    // if (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE) {
    //     qDebug() << "SaveStream: Invalid AVPacket 0: pts or dts is "
    //                 "AV_NOPTS_VALUE.\n";
    //     return false;
    // }

    if (pkt->pts < 0 || pkt->dts < 0) {
        qDebug() << "SaveStream: Invalid AVPacket 0: pts or dts <0.\n";
        return false;
    }

    // 检查流索引（如果是多流）
    if (pkt->stream_index < 0) {
        qDebug()
            << "SaveStream: Invalid AVPacket 0: stream_index is invalid.\n";
        return false;
    }

    // 检查是否是有效的关键帧（可选）
    if (pkt->flags & AV_PKT_FLAG_KEY) {
        // 是关键帧
        // qDebug() << "This is a keyframe.\n";
    }

    return true;
}
