use async_trait::async_trait;
use tokio::sync::mpsc::Sender;

use crate::chopper::error::{Error, Result};
use crate::chopper::functor::Functor;

use crate::chopper::types::{Header, Row};

pub struct ColumnFilterDelete {
    column_index: usize,
}

impl ColumnFilterDelete {
    pub fn new(header: &Header, column_name: &str) -> Result<(Self, Header)> {
        let mut new_header = header.clone();
        let field_names = header.field_names();
        let mut i = 0;
        while i != field_names.len() {
            if field_names[i].eq_ignore_ascii_case(column_name) {
                // remove column
                new_header.field_names_mut().remove(i);
                new_header.field_types_mut().remove(i);
                // return data filter with the column index
                let filter = ColumnFilterDelete { column_index: i };
                return Ok((filter, new_header));
            }
            i += 1;
        }
        Err(Error::from(format!(
            "ColumnFilterDeleteConfig -- field name [{}] not found",
            column_name
        )))
    }
}

#[async_trait]
impl Functor for ColumnFilterDelete {
    async fn write(&mut self, mut row: Box<Row>, output: &mut Sender<Box<Row>>) -> Result<()> {
        row.field_values.remove(self.column_index);
        output.send(row).await.unwrap();
        Ok(())
    }
}
