use oxydsp_flowgraph::{BlockIO, block::Block, io::{In, Out}, tag::TagKey};

#[derive(BlockIO)]
pub struct GraphKiller<T: 'static, K: Send>
{
    #[input]
    input: In<T>,

    #[output]
    output: Out<T>,

    kill_tag: TagKey<K>
}

impl<T: 'static, K: Send + Send + 'static> GraphKiller<T, K>
{
    pub fn new(input: In<T>, kill_on: TagKey<K>) -> (Self, In<T>)
    {
        let (output, port) = oxydsp_flowgraph::io::stream();
        (
            GraphKiller
            {
                input,
                output,
                kill_tag: kill_on,
            },
            port
        )
    }
}

impl<T: 'static, K: Send + Sync + 'static> Block for GraphKiller<T, K>
{
    fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
    {
        let mut reader = self.input.iter();
        let mut writer = self.output.write_push();
        for _ in 0..reader.len().min(writer.len())
        {
            let (data, tag) = reader.next().unwrap().into(); 

            if tag.as_ref().is_some_and(|t| t.retrieve(&self.kill_tag).is_some())
            {
                return oxydsp_flowgraph::block::BlockResult::Exit;
            }

            let _ = writer.push((data, tag).into());
        }


        oxydsp_flowgraph::block::BlockResult::Ok
    }
}
