use std::io::Write;

use crate::Notification;

use super::Response;

pub(crate) struct Writer<'a> {
    output: &'a mut dyn Write,
}

impl<'a> Writer<'a> {
    pub(super) fn new(output: &'a mut dyn Write) -> Self {
        Self { output }
    }

    pub(super) fn write_response(&mut self, response: &Response) {
        let response_str = serde_json::to_string(&response).expect("Response not serializable");
        self.output
            .write_all(format!("Content-length: {}\r\n\r\n", response_str.len()).as_bytes())
            .unwrap();
        self.output
            .write_all(response_str.as_bytes())
            .expect("Could not write response");
        self.output.flush().unwrap();
    }

    pub(super) fn write_notification(&mut self, notification: &Notification) {
        let response_str =
            serde_json::to_string(&notification).expect("Notification not serializable");
        self.output
            .write_all(format!("Content-length: {}\r\n\r\n", response_str.len()).as_bytes())
            .unwrap();
        self.output
            .write_all(response_str.as_bytes())
            .expect("Could not write response");
        self.output.flush().unwrap();
    }
}

#[cfg(test)]
mod test {
    use crate::ResponseError;

    use super::*;

    #[test]
    fn test_response() {
        let response = Response::error(1, ResponseError::MethodNotFound);

        let mut output = Vec::<u8>::new();
        let mut buf = Writer::new(&mut output);
        buf.write_response(&response);

        let output_str = str::from_utf8(&output).unwrap();
        let mut splits = output_str.split("\r\n\r\n");
        let _ = splits.next().unwrap();
        let body = splits.next().unwrap();

        let result = serde_json::from_str::<Response>(body).expect("Invalid json returned");
        assert_eq!(result, response);
    }
}
