use nom::character::complete::{digit1, line_ending};
use nom::combinator::map_res;
use nom::multi::{count, separated_list0, separated_list1};
use nom::IResult;

fn elf_parser(s: &str) -> IResult<&str, usize> {
    let (rest, matched): (&str, Vec<usize>) = separated_list0(line_ending, get_digits)(s)?;
    Ok((rest, matched.iter().sum()))
}

fn get_digits(s: &str) -> IResult<&str, usize> {
    map_res(digit1, str::parse::<usize>)(s)
}

fn all_elf_parse(inp: &str) -> IResult<&str, Vec<usize>> {
    separated_list1(count(line_ending, 2), elf_parser)(inp)
}

pub fn parse(inp: String) -> Vec<usize> {
    if let Ok((_, elves)) = all_elf_parse(&inp) {
        elves.clone()
    } else {
        panic!()
    }
}

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

    #[test]
    fn test_get_digits() {
        assert_eq!(Ok(("", 123)), get_digits("123"));
    }

    #[test]
    fn test_one_line_make_elf() {
        assert_eq!(Ok(("", 123)), elf_parser("123"))
    }

    #[test]
    fn test_multiline_make_elf() {
        assert_eq!(Ok(("", 1368)), elf_parser("123\n456\n789"))
    }

    #[test]
    fn test_multiple_elf() {
        assert_eq!(
            Ok(("\n\n123\n123", 1368)),
            elf_parser("123\n456\n789\n\n123\n123")
        )
    }

    #[test]
    fn test_multiple_elf_parsed() {
        assert_eq!(
            Ok(("", vec![1368, 246])),
            all_elf_parse("123\n456\n789\n\n123\n123")
        )
    }
}