use playr_core::audio::Mode;
use playr_core::columns::{Column, SortKey};
use playr_core::gain::ReplayGain;
use playr_core::settings::Persist;
use crate::config::Program;
use crate::Theme;
#[derive(Debug, Clone, PartialEq)]
pub struct Values {
pub eq: [f32; 3],
pub volume: f32,
pub mode: Mode,
pub replaygain: ReplayGain,
pub theme: Theme,
pub columns: Vec<Column>,
pub sort: Vec<SortKey>,
}
pub fn key(p: Persist, program: Program) -> String {
match p {
Persist::Columns | Persist::Sort => format!("{}.{}", p.name(), program.table()),
_ => p.name().to_string(),
}
}
pub fn encode(p: Persist, values: &Values) -> String {
let names = |names: Vec<String>| names.join(",");
match p {
Persist::Eq => values.eq.map(|db| db.to_string()).join(" "),
Persist::Volume => values.volume.to_string(),
Persist::Mode => name_of(&Mode::NAMES, values.mode).into(),
Persist::ReplayGain => values.replaygain.name().into(),
Persist::Theme => values.theme.name().into(),
Persist::Columns => names(values.columns.iter().map(|c| c.name().into()).collect()),
Persist::Sort => names(values.sort.iter().map(|k| k.text()).collect()),
}
}
pub fn decode(p: Persist, text: &str, values: &mut Values) {
match p {
Persist::Eq => {
let db: Vec<f32> = text
.split(' ')
.filter_map(|n| n.parse().ok())
.filter(|n: &f32| n.abs() <= playr_core::audio::eq::RANGE_DB)
.collect();
if let Ok(eq) = <[f32; 3]>::try_from(db) {
values.eq = eq;
}
}
Persist::Volume => {
if let Some(v) = text.parse::<f32>().ok().filter(|v| (0.0..=1.0).contains(v)) {
values.volume = v;
}
}
Persist::Mode => values.mode = named(&Mode::NAMES, text).unwrap_or(values.mode),
Persist::ReplayGain => {
values.replaygain = named(&ReplayGain::NAMES, text).unwrap_or(values.replaygain)
}
Persist::Theme => values.theme = named(&Theme::NAMES, text).unwrap_or(values.theme),
Persist::Columns => {
let columns: Option<Vec<Column>> = text.split(',').map(Column::named).collect();
if let Some(columns) = columns.filter(|c| !c.is_empty()) {
values.columns = columns;
}
}
Persist::Sort => {
let sort: Option<Vec<SortKey>> = match text {
"" => Some(Vec::new()),
_ => text.split(',').map(SortKey::named).collect(),
};
if let Some(sort) = sort {
values.sort = sort;
}
}
}
}
fn name_of<T: PartialEq + Copy>(names: &[(&'static str, T)], value: T) -> &'static str {
names.iter().find(|n| n.1 == value).map_or("", |n| n.0)
}
fn named<T: Copy>(names: &[(&'static str, T)], text: &str) -> Option<T> {
names.iter().find(|n| n.0 == text).map(|n| n.1)
}