use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
use crate::sql::generators::TableGenerator;
use anyhow::{anyhow, Result};
use figlet_rs::FIGfont;
use std::collections::HashMap;
use std::sync::Arc;
pub struct AsciiArt;
impl TableGenerator for AsciiArt {
fn name(&self) -> &str {
"ASCII_ART"
}
fn columns(&self) -> Vec<DataColumn> {
vec![DataColumn {
name: "line".to_string(),
data_type: DataType::String,
nullable: false,
unique_values: Some(0),
null_count: 0,
metadata: HashMap::new(),
qualified_name: None,
source_table: None,
}]
}
fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
if args.is_empty() {
return Err(anyhow!("ASCII_ART requires at least 1 argument (text)"));
}
let text = match &args[0] {
DataValue::String(s) => s.clone(),
DataValue::Null => return Err(anyhow!("ASCII_ART text cannot be NULL")),
other => other.to_string(),
};
let _font_name = if args.len() > 1 {
match &args[1] {
DataValue::String(s) => s.clone(),
DataValue::Null => "standard".to_string(),
_ => "standard".to_string(),
}
} else {
"standard".to_string()
};
let font =
FIGfont::standard().map_err(|e| anyhow!("Failed to load standard font: {}", e))?;
let ascii_art = font
.convert(&text)
.ok_or_else(|| anyhow!("Failed to convert text to ASCII art"))?;
let mut table = DataTable::new("ascii_art");
table.add_column(DataColumn::new("line"));
for line in ascii_art.to_string().lines() {
table
.add_row(DataRow::new(vec![DataValue::String(line.to_string())]))
.map_err(|e| anyhow!(e))?;
}
Ok(Arc::new(table))
}
fn description(&self) -> &str {
"Generate ASCII art text using FIGlet fonts"
}
fn arg_count(&self) -> usize {
1 }
}
pub struct BigText;
impl TableGenerator for BigText {
fn name(&self) -> &str {
"BIG_TEXT"
}
fn columns(&self) -> Vec<DataColumn> {
AsciiArt.columns()
}
fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
AsciiArt.generate(args)
}
fn description(&self) -> &str {
"Generate big ASCII text (alias for ASCII_ART)"
}
fn arg_count(&self) -> usize {
1
}
}
pub struct Banner;
impl TableGenerator for Banner {
fn name(&self) -> &str {
"BANNER"
}
fn columns(&self) -> Vec<DataColumn> {
vec![DataColumn {
name: "line".to_string(),
data_type: DataType::String,
nullable: false,
unique_values: Some(0),
null_count: 0,
metadata: HashMap::new(),
qualified_name: None,
source_table: None,
}]
}
fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
if args.is_empty() {
return Err(anyhow!("BANNER requires at least 1 argument (text)"));
}
let text = match &args[0] {
DataValue::String(s) => s.clone(),
DataValue::Null => return Err(anyhow!("BANNER text cannot be NULL")),
other => other.to_string(),
};
let border_char = if args.len() > 1 {
match &args[1] {
DataValue::String(s) if !s.is_empty() => s.chars().next().unwrap(),
_ => '*',
}
} else {
'*'
};
let font =
FIGfont::standard().map_err(|e| anyhow!("Failed to load standard font: {}", e))?;
let ascii_art = font
.convert(&text)
.ok_or_else(|| anyhow!("Failed to convert text to ASCII art"))?;
let mut table = DataTable::new("banner");
table.add_column(DataColumn::new("line"));
let lines: Vec<String> = ascii_art
.to_string()
.lines()
.map(|s| s.to_string())
.collect();
let max_width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
let border_line = border_char.to_string().repeat(max_width + 4);
table
.add_row(DataRow::new(vec![DataValue::String(border_line.clone())]))
.map_err(|e| anyhow!(e))?;
for line in lines {
let padded_line = format!(
"{} {:<width$} {}",
border_char,
line,
border_char,
width = max_width
);
table
.add_row(DataRow::new(vec![DataValue::String(padded_line)]))
.map_err(|e| anyhow!(e))?;
}
table
.add_row(DataRow::new(vec![DataValue::String(border_line)]))
.map_err(|e| anyhow!(e))?;
Ok(Arc::new(table))
}
fn description(&self) -> &str {
"Generate ASCII art banner with optional border"
}
fn arg_count(&self) -> usize {
1 }
}