use crate::{media::FileVariant, models::file::FileDetails, types::DynError};
use async_trait::async_trait;
use std::path::PathBuf;
mod image;
mod video;
pub use image::*;
pub use video::*;
pub trait BaseProcessingOptions: Send + Sync {
fn content_type(&self) -> String;
}
#[async_trait]
pub trait VariantProcessor {
type ProcessingOptions: BaseProcessingOptions;
fn get_valid_variants_for_content_type(content_type: &str) -> Vec<FileVariant>;
fn get_content_type_for_variant(file: &FileDetails, variant: &FileVariant) -> String;
fn get_options_for_variant(
file: &FileDetails,
variant: &FileVariant,
) -> Result<Self::ProcessingOptions, DynError>;
async fn process(
origin_file_path: &str,
output_file_path: &str,
options: &Self::ProcessingOptions,
) -> Result<String, DynError>;
async fn create_variant(
file: &FileDetails,
variant: &FileVariant,
file_path: PathBuf,
) -> Result<String, DynError> {
let options = match Self::get_options_for_variant(file, variant) {
Ok(options) => options,
Err(_) => return Ok(file.content_type.clone()),
};
let origin_path = file_path
.join(file.owner_id.as_str())
.join(file.id.as_str());
let origin_file = origin_path.join(FileVariant::Main.to_string());
let origin_file_path = match origin_file.to_str() {
Some(path) => path,
None => return Err("Invalid original file path".into()),
};
let output = origin_path.join(variant.to_string());
let output_path = match output.to_str() {
Some(path) => path,
None => return Err("Invalid output path".into()),
};
Self::process(origin_file_path, output_path, &options).await?;
Ok(options.content_type())
}
}