//! Example of parsing an &str
#![deny(unsafe_code)]
//#![deny(warnings)]
#![feature(proc_macro)]
#![feature(unsize)]
#![no_std]

extern crate cortex_m_rtfm as rtfm;
extern crate f4;
extern crate heapless;

#[macro_use]
extern crate cortex_m_debug;

use rtfm::app;
use heapless::String;
use core::fmt::Write;
use core::marker::Unsize;

// RTFM FRAMEWORK
app! {
    device: f4::stm32f40x,

}

#[derive(Debug)]
enum Command {
    Start,
    Stop,
    Freq(u32),
}

fn f(s: &&str) -> bool {
    !(s == &"")
}

const LEN: usize = 16;

fn parse<'a, A>(s: &str, err: &'a mut String<A>) -> Result<Command, &'a mut String<A>>
where
    A: Unsize<[u8]>,
{
    //let mut iter = s.split(' ').filter(|c| !(c == &""));
    let mut iter = s.split(' ').filter(f);

    match iter.next() {
        Some("Stop") => Ok(Command::Stop),
        Some("Start") => Ok(Command::Start),
        Some("Freq") => match iter.next() {
            Some(fs) => {
                if let Ok(f) = fs.parse::<u32>() {
                    Ok(Command::Freq(f))
                } else {
                    let _ = write!(err, "{}", fs);
                    Err(err)
                }
            }
            let _ = write!(err, "No frequency");
            None => Err(err),
        },
        Some(command) => {
            let _ = write!(err, "{}", command);
            Err(&mut err);
        }
        None => Err("No input"),
    }
}

fn init(_p: init::Peripherals) {
    let mut err: String<[u8; LEN]> = String::new();

    ipln!("init");
    ipln!("{:?}", parse("Start", &mut err)); // works

    ipln!("err {}", err);
    // ipln!("{:?}", parse("  Start  ")); // works with white spaces
    // ipln!("{:?}", parse("  Freq  122  ")); // works with white spaces
    ipln!("{:?}", parse("  Freq  a122  ", &mut err)); // Invalid frequency
    ipln!("err {}", err);

    // ipln!("{:?}", parse("  Freq    ")); // No frequency
    // ipln!("{:?}", parse("")); // No input
}

fn idle() -> ! {
    // Sleep
    loop {
        rtfm::wfi();
    }
}