// SPDX-License-Identifier: MIT OR Apache-2.0
// Copyright 2024 René Ladan <rene0+codeberg@freedom.nl>

use radio_datetime_utils::{
    DST_ANNOUNCED, DST_PROCESSED, DST_SUMMER, LEAP_ANNOUNCED, LEAP_MISSING, LEAP_PROCESSED,
};

use dcf77_utils::DCF77Utils;

// quick and dirty parsing function
fn parse_dst(dst: Option<u8>) -> String {
    if dst.is_none() {
        return String::from("*");
    }
    let mut res = String::from("");
    let s_dst = dst.unwrap();
    if s_dst & DST_ANNOUNCED != 0 {
        res += "announced ";
    }
    if s_dst & DST_PROCESSED != 0 {
        res += "processed ";
    }
    if s_dst & DST_SUMMER != 0 {
        res += "summer";
    }
    res
}

fn str_weekday(day: Option<u8>) -> String {
    String::from(match day {
        Some(0) => "?",
        Some(1) => "Monday",
        Some(2) => "Tuesday",
        Some(3) => "Wednesday",
        Some(4) => "Thursday",
        Some(5) => "Friday",
        Some(6) => "Saturday",
        Some(7) => "Sunday",
        None => "None",
        _ => "<panic>",
    })
}

fn parse_leapsecond(ls: Option<u8>, is_one: Option<bool>) -> String {
    if ls.is_none() {
        return String::from("*");
    }
    let mut res = String::from("");
    let s_ls = ls.unwrap();
    if s_ls & LEAP_ANNOUNCED != 0 {
        res += "announced ";
    }
    if s_ls & LEAP_PROCESSED != 0 {
        res += "processed ";
        res += match is_one {
            Some(true) => " 1-instead-of-0 ",
            Some(false) => "",
            None => "*",
        }
    }
    if s_ls & LEAP_MISSING != 0 {
        res += "missing";
    }

    res
}

fn main() {
    let mut dcf77 = DCF77Utils::default();

    const MSG: &str =
        "0 0101.0010.1100.10 0 010 0 1 1110.000 1 1100.01 1 1001.00 010 0010.0 0010.0100 0N";
    for m in MSG.chars() {
        match m {
            '0' => dcf77.set_current_bit(Some(false)),
            '1' => dcf77.set_current_bit(Some(true)),
            '_' => dcf77.set_current_bit(None),
            'N' => dcf77.force_new_minute(),
            _ => continue,
            // also skip increasing the second counter, as this character is only syntactic sugar
        }
        if !dcf77.increase_second() {
            println!("Bad increase_second at second {}", dcf77.get_old_second());
        }
    }

    dcf77.decode_time(true, false);

    println!("Bit 0={:?}", dcf77.get_bit_0());
    println!(
        "Third party bits=0x{:x}",
        dcf77.get_third_party_buffer().unwrap()
    );
    println!("Call bit={:?}", dcf77.get_call_bit());
    println!("Bit 20={:?}", dcf77.get_bit_20());
    println!(
        "Parities={:?} {:?} {:?}",
        dcf77.get_parity_1(),
        dcf77.get_parity_2(),
        dcf77.get_parity_3()
    );
    let rdt = dcf77.get_radio_datetime();
    println!(
        "Date/time={:?}-{:?}-{:?} {:?}:{:?} {} {} {}",
        rdt.get_year(),
        rdt.get_month(),
        rdt.get_day(),
        rdt.get_hour(),
        rdt.get_minute(),
        str_weekday(rdt.get_weekday()),
        parse_dst(rdt.get_dst()),
        parse_leapsecond(rdt.get_leap_second(), dcf77.leap_second_is_one())
    );
}
