use std::ptr::{null, null_mut};
use rsmpeg::avcodec::AVSubtitle;
use rsmpeg::avutil::AVFrame;
use crate::playback::packet::PacketQueue;
use rsmpeg::ffi::AVRational;
use crate::playback::constant::FRAME_QUEUE_SIZE;
use crate::playback::mutex::{MutexQueue, New};

pub struct FrameData {
    pub pkt_pos: i64,
}

/* Common struct for handling all types of decoded data and allocated render buffers. */
pub struct Frame {
    pub frame: Box<AVFrame>,
    pub sub: Option<Box<AVSubtitle>>,
    pub serial: i64,
    pub pts: f32,           /* presentation timestamp for the frame */
    pub duration: f32,      /* estimated duration of the frame */
    pub pos: i64,          /* byte position of the frame in the input file */
    pub width: i64,
    pub height : i64,
    pub format : i64,
    pub sar : AVRational,
    pub uploaded : bool,
    pub flip_v : bool,
}

pub type MutexFrameQueue = MutexQueue<FrameQueue>;

pub struct FrameQueue {
    pub queue : [Option<Frame>; FRAME_QUEUE_SIZE],
    pub rindex : usize,
    pub windex: usize,
    pub size : usize,
    pub max_size: usize,
    pub keep_last: i64,
    pub rindex_shown: usize,
    pub pktq : Box<PacketQueue>,
}

impl New for FrameQueue {
    fn new() -> Self {
        FrameQueue {
            queue: Default::default(),
            rindex: 0,
            windex: 0,
            size: 0,
            max_size: 0,
            keep_last: 0,
            rindex_shown: 0,
            pktq: Box::new(PacketQueue::new()),
        }
    }
}


impl MutexFrameQueue {
    pub fn signal(&self) {
        let _unused = self.mutex.lock().unwrap();
        self.cond.notify_one();
    }

    pub fn peek(&self) -> &Option<Frame>
    {
        return &self.data.queue[(self.data.rindex + self.data.rindex_shown) % self.data.max_size];
    }


    pub fn peek_next(&self) -> &Option<Frame>
    {
        return &self.data.queue[(self.data.rindex + self.data.rindex_shown + 1) % self.data.max_size];
    }

    pub fn peek_last(&self) -> &Option<Frame>{
        &self.data.queue[self.data.rindex]
    }

    pub fn peek_writable(&mut self) -> &Option<Frame> {
        /* wait until we have space to put a new frame */
        let mut m = self.mutex.lock().unwrap();
        let pq = &mut self.data;
        while pq.size >= pq.max_size && !pq.pktq.abort_request {
            m = self.cond.wait(m).unwrap();
        }
        if pq.pktq.abort_request {
            return &None;
        }
        & pq.queue[pq.windex]
    }
}
