extern crate alloc;

use alloc::{string::String, vec, vec::Vec};

use super::{CapacityError, InlineArray};
use crate::Str;

#[test]
fn new_starts_empty() {
    let arr = InlineArray::<u8, 4>::new();
    assert_eq!(arr.capacity(), 4);
    assert_eq!(arr.len(), 0);
    assert!(arr.is_empty());
    assert!(!arr.is_full());
}

#[test]
fn push_and_pop_work() {
    let mut arr = InlineArray::<u8, 2>::new();
    assert!(arr.push(1).is_ok());
    assert!(arr.push(2).is_ok());
    assert!(arr.is_full());
    assert_eq!(arr.push(3), Err(3));

    assert_eq!(arr.pop(), Some(2));
    assert_eq!(arr.pop(), Some(1));
    assert_eq!(arr.pop(), None);
}

#[test]
fn collect_from_string_refs_into_inline_array_of_str() {
    let input = vec![
        String::from("alpha"),
        String::from("beta"),
        String::from("gamma"),
    ];

    let out: InlineArray<Str<16>, 16> = input.iter().map(|s| Str::<16>::from(s.as_str())).collect();

    assert_eq!(out.len(), 3);
    assert_eq!(out[0].as_str(), "alpha");
    assert_eq!(out[1].as_str(), "beta");
    assert_eq!(out[2].as_str(), "gamma");
}

#[test]
fn try_from_slice_returns_capacity_error_on_overflow() {
    let input = [
        String::from("zero"),
        String::from("one"),
        String::from("two"),
    ];

    let out = InlineArray::<String, 2>::try_from(&input[..]);
    assert_eq!(out, Err(CapacityError));
}

#[test]
fn try_from_slice_accepts_shorter_input() {
    let input = [String::from("zero"), String::from("one")];

    let out = InlineArray::<String, 4>::try_from(&input[..]).unwrap();
    assert_eq!(out.len(), 2);
    assert_eq!(out.as_slice()[0], "zero");
    assert_eq!(out.as_slice()[1], "one");
}

#[test]
#[should_panic(expected = "stx::InlineArray capacity exceeded")]
fn collect_panics_when_capacity_is_exceeded() {
    let input: Vec<u8> = vec![1, 2, 3];
    let _out: InlineArray<u8, 2> = input.into_iter().collect();
}
