use std::path::Path;
use crate::plugin::Plugin;
use crate::string_types::ExtractedString;
use crate::io::{EspWriter, RawEspData};
use super::delta::{TranslationDelta, RecordChange, RecordId};
pub struct PluginEditor {
plugin: Plugin,
modifications: TranslationDelta,
}
impl PluginEditor {
pub fn new(plugin: Plugin) -> Self {
Self {
plugin,
modifications: TranslationDelta::new(),
}
}
pub fn apply_translation(
&mut self,
translation: &ExtractedString,
) -> Result<bool, Box<dyn std::error::Error>> {
let translations = vec![translation.clone()];
let result = self.apply_translations(translations)?;
Ok(result > 0)
}
pub fn apply_translations(
&mut self,
translations: Vec<ExtractedString>,
) -> Result<usize, Box<dyn std::error::Error>> {
let _old_modified_count = self.modifications.len();
let translation_map: std::collections::HashMap<_, _> = translations
.into_iter()
.map(|t| (t.get_unique_key(), t))
.collect();
self.plugin.apply_translation_map(&translation_map)?;
let new_modified_count = translation_map.len();
let applied_count = new_modified_count;
for (key, trans) in translation_map.iter() {
let change = RecordChange {
record_id: RecordId::new(
self.extract_form_id_from_key(key),
trans.editor_id.clone(),
),
subrecord_type: trans.get_string_type(),
old_value: String::new(), new_value: trans.text.clone(),
applied_at: std::time::Instant::now(),
};
self.modifications.add_change(change);
}
Ok(applied_count)
}
fn extract_form_id_from_key(&self, key: &str) -> u32 {
let parts: Vec<&str> = key.split('|').collect();
if parts.len() >= 2 {
let form_id_part = parts[1].split('|').next().unwrap_or("00000000");
u32::from_str_radix(&form_id_part[..8], 16).unwrap_or(0)
} else {
0
}
}
pub fn is_modified(&self) -> bool {
!self.modifications.is_empty()
}
pub fn modified_count(&self) -> usize {
self.modifications.len()
}
pub fn get_modifications(&self) -> &TranslationDelta {
&self.modifications
}
pub fn undo(&mut self) -> Result<(), Box<dyn std::error::Error>> {
self.modifications
.undo()
.map_err(|e| e.into())
.map(|_| ())
}
pub fn redo(&mut self) -> Result<(), Box<dyn std::error::Error>> {
self.modifications
.redo()
.map_err(|e| e.into())
.map(|_| ())
}
pub fn save(
&self,
writer: &dyn EspWriter,
path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
let mut output = Vec::new();
self.plugin.write_to_buffer(&mut output)?;
let data = RawEspData { bytes: output };
writer.write(&data, path)?;
Ok(())
}
pub fn save_to_original(
&self,
writer: &dyn EspWriter,
) -> Result<(), Box<dyn std::error::Error>> {
let path = self.plugin.path.clone();
self.save(writer, &path)
}
pub fn plugin(&self) -> &Plugin {
&self.plugin
}
pub fn plugin_mut(&mut self) -> &mut Plugin {
&mut self.plugin
}
pub fn clear_modifications(&mut self) {
self.modifications.clear();
}
pub fn summary(&self) -> String {
format!(
"插件: {}, 修改状态: {}, {}",
self.plugin.get_name(),
if self.is_modified() {
"已修改"
} else {
"未修改"
},
self.modifications.summary()
)
}
}
impl Plugin {
pub(crate) fn write_to_buffer(
&self,
output: &mut Vec<u8>,
) -> Result<(), Box<dyn std::error::Error>> {
self.write_record(&self.header, output)?;
for group in &self.groups {
self.write_group(group, output)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_plugin_editor_creation() {
}
#[test]
fn test_editor_state() {
}
}