use crate::slide::Slide;
use crate::slides::demo::Demo;
use crate::slides::projects::Projects;
use crate::slides::standard_slide::{StandardSlide, StandardSlideConfig};
use crate::slides::title::Title;
use config::Config;
use serde::Deserialize;
use std::path::{Path, PathBuf};

#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum SlideType {
    Title { title: String },
    Demo,
    Projects,
    StandardSlide(StandardSlideConfig),
}

impl SlideType {
    pub async fn slide(self, asset_dir: &Path) -> Box<dyn Slide> {
        match self {
            SlideType::Title { title } => Title::new(title),
            SlideType::Demo => Demo::new(),
            SlideType::Projects => Projects::new(),
            SlideType::StandardSlide(cfg) => StandardSlide::new(cfg, asset_dir).await,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct SlideDeckConfig {
    pub assets_dir: PathBuf,
    pub slides: Vec<SlideType>,
}

impl SlideDeckConfig {
    pub fn new(src: &Path) -> Result<Self, config::ConfigError> {
        let cfg = Config::builder()
            .add_source(config::File::from(src))
            .build()?;

        cfg.try_deserialize()
    }
}
