use crate::decode::*;
use crate::encode::*;
use crate::*;

#[test]
fn unsigned() {
    for value in [10, 124, 23532, 193884757] {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_unsigned(&mut buffer, value).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_unsigned(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, value);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_u8(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_u8(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_u16(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_u16(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_u32(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_u32(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_u64(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_u64(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }
}

#[test]
fn signed() {
    for value in [10, -10, -124, -23532, -193884757] {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_signed(&mut buffer, value).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_signed(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, value);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_i8(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_i8(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_i16(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_i16(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_i32(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_i32(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }

    {
        let mut data = [0u8; 10];
        let mut buffer = WriteBuffer::from(&mut data);

        write_i64(&mut buffer, 5).unwrap_or_else(|_| panic!());

        let mut buffer = ReadBuffer::from(&data);
        let res = read_i64(&mut buffer).unwrap_or_else(|_| panic!());

        assert_eq!(res, 5);
    }
}

#[test]
fn ascii() {
    let mut data = [0u8; 10];
    let mut buffer = WriteBuffer::from(&mut data);

    write_str(&mut buffer, "it works!").unwrap_or_else(|_| panic!());

    let mut buffer = ReadBuffer::from(&data);
    let res = read_str(&mut buffer).unwrap_or_else(|_| panic!());

    assert_eq!(res, "it works!");
}

#[test]
fn bin() {
    let value = b"njdsfiodsjf90dsuf90ewjfniewhf8s9dhf084hdfuigf847gfew98fgheghf";

    let mut data = [0u8; 100];
    let mut buffer = WriteBuffer::from(&mut data);

    write_bin(&mut buffer, value).unwrap_or_else(|_| panic!());

    let mut buffer = ReadBuffer::from(&data);
    let res = read_bin(&mut buffer).unwrap_or_else(|_| panic!());

    assert_eq!(res, value);
}

#[test]
fn boolean() {
    let mut data = [0u8; 10];
    let mut buffer = WriteBuffer::from(&mut data);

    write_bool(&mut buffer, true).unwrap_or_else(|_| panic!());
    write_bool(&mut buffer, false).unwrap_or_else(|_| panic!());

    let mut buffer = ReadBuffer::from(&data);

    let should_be_true = read_bool(&mut buffer).unwrap_or_else(|_| panic!());
    let should_be_false = read_bool(&mut buffer).unwrap_or_else(|_| panic!());

    assert_eq!(should_be_true, true);
    assert_eq!(should_be_false, false);
}

#[test]
fn float() {
    let mut data = [0u8; 100];
    let mut buffer = WriteBuffer::from(&mut data);

    write_f32(&mut buffer, -19.24452).unwrap_or_else(|_| panic!());
    write_f64(&mut buffer, 10.2434).unwrap_or_else(|_| panic!());

    let mut buffer = ReadBuffer::from(&data);

    let neg = read_f32(&mut buffer).unwrap_or_else(|_| panic!());
    let pos = read_f64(&mut buffer).unwrap_or_else(|_| panic!());

    assert_eq!(neg, -19.24452);
    assert_eq!(pos, 10.2434);
}

#[test]
fn array() {
    let mut data = [0u8; 100];
    let mut buffer = WriteBuffer::from(&mut data);

    write_array(&mut buffer, None).unwrap_or_else(|_| panic!());
    for len in [10, 123, 1234, 123456] {
        write_array(&mut buffer, Some(len)).unwrap_or_else(|_| panic!());
    }

    let mut buffer = ReadBuffer::from(&data);

    let len = read_array(&mut buffer).unwrap_or_else(|_| panic!());
    assert!(matches!(len, None));

    for len_ in [10, 123, 1234, 123456] {
        let res = read_array(&mut buffer).unwrap_or_else(|_| panic!());
        match res {
            Some(len) => assert_eq!(len, len_),
            None => panic!(),
        }
    }
}

#[test]
fn map() {
    let mut data = [0u8; 100];
    let mut buffer = WriteBuffer::from(&mut data);

    write_map(&mut buffer, None).unwrap_or_else(|_| panic!());
    for len in [10, 123, 1234, 123456] {
        write_map(&mut buffer, Some(len)).unwrap_or_else(|_| panic!());
    }

    let mut buffer = ReadBuffer::from(&data);

    let len = read_map(&mut buffer).unwrap_or_else(|_| panic!());
    assert!(matches!(len, None));

    for len_ in [10, 123, 1234, 123456] {
        let res = read_map(&mut buffer).unwrap_or_else(|_| panic!());
        match res {
            Some(len) => assert_eq!(len, len_),
            None => panic!(),
        }
    }
}

#[test]
fn marker() {
    let mut data = [0b11011110; 1];
    let mut buffer = WriteBuffer::from(&mut data);

    write_null(&mut buffer).unwrap_or_else(|_| panic!());

    let mut buffer = ReadBuffer::from(&data);
    let marker = peek_marker(&mut buffer).unwrap_or_else(|_| panic!());
    assert!(matches!(marker, Marker::Null));
    assert_eq!(buffer.consumed(), 0);

    let marker = read_marker(&mut buffer).unwrap_or_else(|_| panic!());
    assert!(matches!(marker, Marker::Null));
    assert_eq!(buffer.consumed(), 1);
}

#[test]
fn mismatch_array() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_array(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_ascii() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_str(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_bin() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_bin(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_bool() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_bool(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_float() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_f32(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_f64(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_map() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_map(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_signed() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_signed(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_i8(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_i16(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_i32(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_i64(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}

#[test]
fn mismatch_unsigned() {
    let data = [0b11011110; 10];
    let mut buffer = ReadBuffer::from(&data);

    assert!(read_unsigned(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_u8(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_u16(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_u32(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);

    assert!(read_u64(&mut buffer).is_err_and(|error| error == Error::Unexpected));
    assert_eq!(buffer.consumed(), 0);
}
