#include "nodes/base/base.hpp"
#include "nodes/stream/streamNode.hpp"

namespace Node
{

void StreamNode::work()
{
    printf("StreamNode %s\n", name_.c_str());
    printf("stram url: %s\n", stream_url_.c_str());
    printf("Decode type: %d\n", static_cast<int>(decode_type_));

    if (decode_type_ == DecodeType::CPU)
    {
        work_cpu();
    }
    else
    {
        work_gpu();
    }
}


void StreamNode::work_cpu()
{
    while (running_)
    {
        cv::Mat frame;
        cap_->read(frame);
        frame_count_++;
        if (frame_count_ % skip_frame_ != 0)
        {
            // printf("Skip frame %d\n", frame_count_);
            continue;
        }
        if (frame.empty())
        {
            std::cerr << "Error: cannot read frame" << std::endl;
            break;
        }

        auto metaData = std::make_shared<meta::MetaData>();
        metaData->image = frame;
        metaData->from = name_;

        for (auto& output_buffer : output_buffers_)
        {
            output_buffer.second->push(metaData);
            // printf("Node %s push data to %s\n", name_.c_str(), output_buffer.first.c_str());
        }
    }
}

void StreamNode::work_gpu()
{
    uint8_t* packet_data = nullptr;
    int packet_size = 0;
    int64_t pts = 0;

    demuxer_->get_extra_data(&packet_data, &packet_size);
    decoder_->decode(packet_data, packet_size);

	printf("packet_size = %d\n", packet_size);

    unsigned int frame_index = 0;
    while(running_)
    {
        demuxer_->demux(&packet_data, &packet_size, &pts);
        if (packet_size <= 0 || !running_)
        {
            break;
        }
        int ndecoded_frame = decoder_->decode(packet_data, packet_size, pts);
        for(int i = 0; i < ndecoded_frame; ++i){
            cv::Mat frame(decoder_->get_height(), decoder_->get_width(), CV_8UC3, decoder_->get_frame(&pts, &frame_index));
            frame_index = frame_index + 1;
            
            frame_count_++;
            if (frame_count_ % skip_frame_ != 0)
            {
                continue;
            }

            auto metaData = std::make_shared<meta::MetaData>();
            metaData->image = frame;
            metaData->from = name_;

            for (auto& output_buffer : output_buffers_)
            {
                output_buffer.second->push(metaData);
                // printf("Node %s push data to %s\n", name_.c_str(), output_buffer.first.c_str());
            }
        }
    };
	printf("C++ Demo: %d frames\n", frame_index);
}


}   // namespace Node