use std::collections::HashMap;
use image::Rgb;
use crate::archive::WszArchive;
use crate::error::{Result, WszError};
#[derive(Debug, Clone)]
pub struct PleditSettings {
pub normal: Option<Rgb<u8>>,
pub current: Option<Rgb<u8>>,
pub normal_bg: Option<Rgb<u8>>,
pub selected_bg: Option<Rgb<u8>>,
pub font: Option<String>,
pub custom: HashMap<String, String>,
}
impl PleditSettings {
fn new() -> Self {
Self {
normal: None,
current: None,
normal_bg: None,
selected_bg: None,
font: None,
custom: HashMap::new(),
}
}
pub fn from_archive(archive: &WszArchive) -> Result<Self> {
let pledit_txt = archive
.iter()
.find(|(name, _)| name.split('/').last().unwrap().to_lowercase() == "pledit.txt")
.ok_or(WszError::NotFound("pledit.txt".to_string()))?;
Self::from_string(&String::from_utf8_lossy(pledit_txt.1).to_string())
}
pub fn from_string(content: &str) -> Result<Self> {
let mut settings = Self::new();
let mut current_section = String::new();
for (line_num, line) in content.lines().enumerate() {
let line = line.trim();
if line.is_empty() {
continue;
}
if line.starts_with(';') {
continue;
}
if line.starts_with('[') && line.ends_with(']') {
current_section = line[1..line.len() - 1].to_string();
continue;
}
if let Some(pos) = line.find('=') {
let key = line[..pos].trim();
let value = line[pos + 1..].trim();
match current_section.as_str() {
"Text" => {
match key.to_lowercase().as_str() {
"normal" => {
settings.normal = Some(parse_hex_color(value)?);
}
"current" => {
settings.current = Some(parse_hex_color(value)?);
}
"normalbg" => {
settings.normal_bg = Some(parse_hex_color(value)?);
}
"selectedbg" => {
settings.selected_bg = Some(parse_hex_color(value)?);
}
"font" => {
settings.font = Some(value.to_string());
}
_ => {
settings.custom.insert(key.to_string(), value.to_string());
}
}
}
_ if !current_section.is_empty() => {
let full_key = format!("{}.{}", current_section, key);
settings.custom.insert(full_key, value.to_string());
}
_ => {
return Err(WszError::InvalidFormat {
line: line_num + 1,
error: "Key-value pair outside of any section".to_string(),
});
}
}
} else {
return Err(WszError::InvalidFormat {
line: line_num + 1,
error: format!("Invalid line format: '{}'", line),
});
}
}
Ok(settings)
}
}
fn parse_hex_color(hex: &str) -> Result<Rgb<u8>> {
let hex = hex.trim_start_matches('#');
if hex.len() != 6 {
return Err(WszError::InvalidFormat {
line: 0,
error: format!("Invalid hex color format: '{}'", hex),
});
}
let r = u8::from_str_radix(&hex[0..2], 16).map_err(|_| WszError::InvalidFormat {
line: 0,
error: format!("Invalid hex value for red: '{}'", &hex[0..2]),
})?;
let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| WszError::InvalidFormat {
line: 0,
error: format!("Invalid hex value for green: '{}'", &hex[2..4]),
})?;
let b = u8::from_str_radix(&hex[4..6], 16).map_err(|_| WszError::InvalidFormat {
line: 0,
error: format!("Invalid hex value for blue: '{}'", &hex[4..6]),
})?;
Ok(Rgb([r, g, b]))
}
impl Default for PleditSettings {
fn default() -> Self {
Self::new()
}
}