use bytes::Bytes;
use std::{fmt, fmt::Formatter};

pub enum PayloadError {}

// TODO: support stream data
#[derive(Clone, serde::Serialize)]
pub enum Payload {
    None,
    Bytes(Bytes),
}

impl std::fmt::Debug for Payload {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        format_payload_print(self, f)
    }
}

impl std::fmt::Display for Payload {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        format_payload_print(self, f)
    }
}

fn format_payload_print(payload: &Payload, f: &mut Formatter<'_>) -> fmt::Result {
    match payload {
        Payload::Bytes(bytes) => f.write_fmt(format_args!("{} bytes", bytes.len())),
        Payload::None => f.write_str("Empty"),
    }
}

impl std::convert::From<String> for Payload {
    fn from(s: String) -> Self {
        Payload::Bytes(Bytes::from(s))
    }
}

impl std::convert::From<&'_ String> for Payload {
    fn from(s: &String) -> Self {
        Payload::Bytes(Bytes::from(s.to_owned()))
    }
}

impl std::convert::From<Bytes> for Payload {
    fn from(bytes: Bytes) -> Self {
        Payload::Bytes(bytes)
    }
}

impl std::convert::From<()> for Payload {
    fn from(_: ()) -> Self {
        Payload::None
    }
}
impl std::convert::From<Vec<u8>> for Payload {
    fn from(bytes: Vec<u8>) -> Self {
        Payload::Bytes(Bytes::from(bytes))
    }
}

impl std::convert::From<&str> for Payload {
    fn from(s: &str) -> Self {
        s.to_string().into()
    }
}
