use crate::{fm_demod::Sample, sync::SyncEvent};

pub struct VideoLine {
    pub samples: Vec<Sample>,
}

pub struct VideoFrame {
    pub lines: Vec<VideoLine>,
}

const LINES_PER_FRAME: usize = 480; // NTSC (576 for PAL)

pub struct LineAssembler<I> {
    pub inner: I,
    pub current_line: Vec<Sample>,
    pub current_frame: Vec<VideoLine>,
}

impl<I> LineAssembler<I> {
    pub fn new(inner: I) -> Self {
        Self {
            inner,
            current_line: Vec::new(),
            current_frame: Vec::new(),
        }
    }
}

impl<I, E> Iterator for LineAssembler<I>
where
    I: Iterator<Item = Result<SyncEvent, E>>,
{
    type Item = Result<VideoFrame, E>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.inner.next()? {
                Ok(SyncEvent::VideoSample(s)) => {
                    self.current_line.push(s);
                }
                Ok(SyncEvent::HSync) => {
                    let line = VideoLine {
                        samples: std::mem::take(&mut self.current_line),
                    };
                    self.current_frame.push(line);

                    if self.current_frame.len() >= LINES_PER_FRAME {
                        let frame = VideoFrame {
                            lines: std::mem::take(&mut self.current_frame),
                        };
                        return Some(Ok(frame));
                    }
                }
                Ok(SyncEvent::VSync) => {
                    // test without vsync
                }
                Err(e) => return Some(Err(e)),
            }
        }
    }
}

// impl<I, E> Iterator for LineAssembler<I>
// where
//     I: Iterator<Item = Result<SyncEvent, E>>,
// {
//     type Item = Result<VideoFrame, E>;
//
//     fn next(&mut self) -> Option<Self::Item> {
//         loop {
//             match self.inner.next()? {
//                 Ok(SyncEvent::VideoSample(s)) => {
//                     self.current_line.push(s);
//                 }
//                 Ok(SyncEvent::HSync) => {
//                     // Save the finished line
//                     let line = VideoLine {
//                         samples: std::mem::take(&mut self.current_line),
//                     };
//
//                     self.current_frame.push(line);
//                 }
//                 Ok(SyncEvent::VSync) => {
//                     // Frame finished
//                     let frame = VideoFrame {
//                         lines: std::mem::take(&mut self.current_frame),
//                     };
//                     self.current_line.clear();
//                     return Some(Ok(frame));
//                 }
//                 Err(e) => return Some(Err(e)),
//             }
//         }
//     }
// }
