pub const SLIP_BOUNDARY: u8 = 0xC0;
const SLIP_ESC: u8 = 0xDB;
const SLIP_ESC_END: u8 = 0xDC;
const SLIP_ESC_ESC: u8 = 0xDD;

/// Encapsulates a raw byte payload into a valid SLIP packet, performing byte stuffing (escaping).
pub fn encode_packet(payload: &[u8]) -> Vec<u8> {
    let mut encoded = Vec::with_capacity(payload.len() + 2);
    encoded.push(SLIP_BOUNDARY);

    for &byte in payload {
        match byte {
            SLIP_BOUNDARY => {
                encoded.push(SLIP_ESC);
                encoded.push(SLIP_ESC_END);
            }
            SLIP_ESC => {
                encoded.push(SLIP_ESC);
                encoded.push(SLIP_ESC_ESC);
            }
            _ => encoded.push(byte),
        }
    }

    encoded.push(SLIP_BOUNDARY);
    encoded
}

/// Primitive packet extractor: Scans the incoming buffer for SLIP boundaries and extracts sliced payloads.
///
/// # Note
/// This method currently isolates data slices between boundaries. In a strict full-stack protocol implementation,
/// an inplace or allocated un-escaping pass (converting `0xDB 0xDC` back to `0xC0`, etc.) would follow here.
pub fn parse_responses(buffer: &[u8]) -> Vec<&[u8]> {
    let mut packets = Vec::new();
    let mut start = None;

    for (idx, &byte) in buffer.iter().enumerate() {
        if byte == SLIP_BOUNDARY {
            if let Some(s) = start {
                if idx > s + 1 {
                    packets.push(&buffer[s + 1..idx]);
                }
                start = Some(idx);
            } else {
                start = Some(idx);
            }
        }
    }
    packets
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_encode_basic() {
        let raw_data = [0x01, 0x02, 0x03];
        let encoded = encode_packet(&raw_data);

        // Packet must start and end with SLIP_BOUNDARY, enclosing the raw data
        assert_eq!(encoded[0], SLIP_BOUNDARY);
        assert_eq!(encoded[1..4], raw_data);
        assert_eq!(encoded[4], SLIP_BOUNDARY);
        assert_eq!(encoded.len(), 5);
    }

    #[test]
    fn test_encode_escaping() {
        // Data stream containing critical SLIP control bytes that require escaping
        let raw_data = [0x01, SLIP_BOUNDARY, 0x02, SLIP_ESC, 0x03];
        let encoded = encode_packet(&raw_data);

        // Expected byte stuffing outcome:
        // [C0]  -> Start boundary
        // 01    -> Literal data
        // DB DC -> Escaped SLIP_BOUNDARY
        // 02    -> Literal data
        // DB DD -> Escaped SLIP_ESC
        // 03    -> Literal data
        // [C0]  -> End boundary
        let expected = vec![
            SLIP_BOUNDARY,
            0x01,
            SLIP_ESC,
            SLIP_ESC_END,
            0x02,
            SLIP_ESC,
            SLIP_ESC_ESC,
            0x03,
            SLIP_BOUNDARY,
        ];
        assert_eq!(encoded, expected);
    }

    #[test]
    fn test_parse_responses_single_packet() {
        let buffer = vec![SLIP_BOUNDARY, 0x05, 0x06, SLIP_BOUNDARY];
        let packets = parse_responses(&buffer);

        assert_eq!(packets.len(), 1);
        assert_eq!(packets[0], &[0x05, 0x06]);
    }

    #[test]
    fn test_parse_responses_multiple_packets() {
        let buffer = vec![
            SLIP_BOUNDARY,
            0x01,
            SLIP_BOUNDARY,
            SLIP_BOUNDARY,
            0x02,
            0x03,
            SLIP_BOUNDARY,
        ];
        let packets = parse_responses(&buffer);

        assert_eq!(packets.len(), 2);
        assert_eq!(packets[0], &[0x01]);
        assert_eq!(packets[1], &[0x02, 0x03]);
    }

    #[test]
    fn test_parse_responses_empty_and_invalid() {
        // Back-to-back boundaries or trailing fragments without an end boundary
        let buffer = vec![SLIP_BOUNDARY, SLIP_BOUNDARY, 0x01, 0x02];
        let packets = parse_responses(&buffer);

        // Should ignore zero-length packets and discard unclosed fragments
        assert!(packets.is_empty());
    }
}
