use std::borrow::Cow;
use fancy_regex::Captures;
use crate::helper::{
date::excel_to_date_time_jiff,
utils::compile_regex,
};
const DATE_FORMAT_REPLACEMENTS: &[(&str, &str)] = &[
("\\", ""),
("am/pm", "%P"),
("ggge", "%Y"),
("e", "%Y"),
("yyyy", "%Y"),
("yy", "%y"),
("mmmmm", "%b"),
("mmmm", "%B"),
("mmm", "%b"),
(":mm", ":%M"),
("mm:", "%M:"),
("mm", "MM"),
("m", "%-m"),
("MM", "%m"),
("dddd", "%A"),
("ddd", "%a"),
("dd", "D"),
("d", "%-d"),
("D", "%d"),
("ss", "%S"),
(".s", "%f"),
];
const DATE_FORMAT_REPLACEMENTS_24: &[(&str, &str)] = &[("hh", "%H"), ("h", "%-H")];
const DATE_FORMAT_REPLACEMENTS_12: &[(&str, &str)] = &[("hh", "%I"), ("h", "%-I")];
pub(crate) fn format_as_date(value: f64, format: &str) -> Cow<'_, str> {
let format = Cow::Borrowed(format);
let re = compile_regex!(r"^(\[[0-9A-Za-z]*\])*(\[\$[A-Z]*-[0-9A-F]*\])");
let format = re.replace_all(&format, r"");
let re = compile_regex!(r#"(?:^|")([^"]*)(?:$|")"#);
let mut format = re.replace_all(&format, |caps: &Captures| {
let caps_string = caps.get(0).unwrap().as_str();
caps_string.to_lowercase()
});
let blocks: Vec<&str> = format.split('"').collect();
let mut converted_blocks: Vec<String> = Vec::new();
let mut i = 0;
for block in blocks {
let mut block = block.to_string();
if i % 2 == 0 {
for (before, after) in DATE_FORMAT_REPLACEMENTS {
block = block.replace(before, after);
}
if block.contains("%P") {
for (before, after) in DATE_FORMAT_REPLACEMENTS_12 {
block = block.replace(before, after);
}
} else {
if block.contains("[h]") {
let hours = value * 24f64;
block = block.replace("[h]", &hours.to_string());
converted_blocks.push(block);
continue;
}
for (before, after) in DATE_FORMAT_REPLACEMENTS_24 {
block = block.replace(before, after);
}
}
}
converted_blocks.push(block);
i += 1;
}
format = Cow::Owned(converted_blocks.join(r""));
let re = compile_regex!(r#""(.*)""#);
let format = re.replace_all(&format, |caps: &Captures| {
let caps_string = caps.get(0).unwrap().as_str();
caps_string.to_lowercase()
});
let date_obj = excel_to_date_time_jiff(value);
Cow::Owned(date_obj.strftime(format.as_bytes()).to_string())
}