use crate::error::{CliError, Result};
use glyph_core::{Frame, Glyph};
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
pub fn create_glyph(
input_files: Vec<PathBuf>,
output: PathBuf,
default_duration: u32,
) -> Result<()> {
let mut first_content = String::new();
File::open(&input_files[0])
.map_err(|e| {
CliError::File(format!(
"Failed to open {}: {}",
input_files[0].display(),
e
))
})?
.read_to_string(&mut first_content)?;
let lines: Vec<&str> = first_content.lines().collect();
let height = lines.len() as u32;
let width = lines.iter().map(|line| line.len()).max().unwrap_or(0) as u32;
let mut glyph = Glyph::new(width, height, default_duration);
for path in input_files {
let mut content = String::new();
File::open(&path)
.map_err(|e| CliError::File(format!("Failed to open {}: {}", path.display(), e)))?
.read_to_string(&mut content)?;
let mut padded_content = String::new();
for line in content.lines() {
let padding = " ".repeat((width as usize).saturating_sub(line.len()));
padded_content.push_str(line);
padded_content.push_str(&padding);
padded_content.push('\n');
}
while padded_content.lines().count() < height as usize {
padded_content.push_str(&" ".repeat(width as usize));
padded_content.push('\n');
}
if padded_content.ends_with('\n') {
padded_content.pop();
}
let frame = Frame::new(padded_content);
glyph.add_frame(frame).map_err(|e| {
CliError::File(format!(
"Failed to add frame from {}: {}",
path.display(),
e
))
})?;
}
let mut output_file = File::create(&output).map_err(|e| {
CliError::File(format!(
"Failed to create output file {}: {}",
output.display(),
e
))
})?;
glyph
.write(&mut output_file)
.map_err(|e| CliError::File(format!("Failed to write Glyph file: {}", e)))?;
println!("Created Glyph animation with {} frames", glyph.frames.len());
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use tempfile::TempDir;
fn create_test_file(dir: &TempDir, name: &str, content: &str) -> PathBuf {
let path = dir.path().join(name);
let mut file = File::create(&path).unwrap();
writeln!(file, "{}", content).unwrap();
path
}
#[test]
fn test_create_single_frame() {
let temp_dir = TempDir::new().unwrap();
let input = create_test_file(&temp_dir, "frame1.txt", "abc\ndef");
let output = temp_dir.path().join("output.glyph");
create_glyph(vec![input], output.clone(), 100).unwrap();
let mut file = File::open(output).unwrap();
let glyph = Glyph::read(&mut file).unwrap();
assert_eq!(glyph.frames.len(), 1);
assert_eq!(glyph.frames[0].content, "abc\ndef");
}
#[test]
fn test_create_multiple_frames() {
let temp_dir = TempDir::new().unwrap();
let input1 = create_test_file(&temp_dir, "frame1.txt", "abc\ndef");
let input2 = create_test_file(&temp_dir, "frame2.txt", "ABC\nDEF");
let output = temp_dir.path().join("output.glyph");
create_glyph(vec![input1, input2], output.clone(), 100).unwrap();
let mut file = File::open(output).unwrap();
let glyph = Glyph::read(&mut file).unwrap();
assert_eq!(glyph.frames.len(), 2);
assert_eq!(glyph.frames[0].content, "abc\ndef");
assert_eq!(glyph.frames[1].content, "ABC\nDEF");
}
#[test]
fn test_create_with_padding() {
let temp_dir = TempDir::new().unwrap();
let input1 = create_test_file(&temp_dir, "frame1.txt", "abcd\nefgh"); let input2 = create_test_file(&temp_dir, "frame2.txt", "ab\nef"); let output = temp_dir.path().join("output.glyph");
create_glyph(vec![input1, input2], output.clone(), 100).unwrap();
let mut file = File::open(output).unwrap();
let glyph = Glyph::read(&mut file).unwrap();
assert_eq!(glyph.frames.len(), 2);
assert_eq!(glyph.frames[0].content, "abcd\nefgh");
assert_eq!(glyph.frames[1].content, "ab \nef "); }
#[test]
fn test_create_with_invalid_input() {
let temp_dir = TempDir::new().unwrap();
let output = temp_dir.path().join("output.glyph");
let result = create_glyph(vec![PathBuf::from("nonexistent.txt")], output.clone(), 100);
assert!(result.is_err());
}
}