use std::path::PathBuf;

use clap::Parser;

use ambient_ci::{
    cloud_init::{CloudInitError, LocalDataStoreBuilder},
    image_store::ImageStoreError,
    qemu::QemuError,
    runlog::RunLog,
    util::UtilError,
    vdrive::VirtualDriveError,
};

use super::{AmbientError, Config, Leaf};

/// Create a cloud-init local data store ISO file.
#[derive(Debug, Parser)]
pub struct CloudInit {
    /// The name of the ISO file.
    #[clap(long)]
    filename: PathBuf,

    /// Commands to run via cloud-init.
    #[clap(long)]
    runcmd: Vec<String>,

    /// Enable networking?
    #[clap(long)]
    network: bool,
}

impl Leaf for CloudInit {
    fn run(&self, _config: &Config, _runlog: &mut RunLog) -> Result<(), AmbientError> {
        let mut ds = LocalDataStoreBuilder::default()
            .with_network(self.network)
            .with_hostname("ambient")
            .with_bootcmd("echo xyzzy2")
            .with_bootcmd("echo more bootcmd");
        for runcmd in self.runcmd.iter() {
            ds = ds.with_runcmd(runcmd);
        }
        let ds = ds.build().map_err(ImageError::CloudInit)?;
        ds.iso(&self.filename).map_err(ImageError::CloudInit)?;
        Ok(())
    }
}

#[derive(Debug, thiserror::Error)]
pub enum ImageError {
    #[error(transparent)]
    Qemu(#[from] QemuError),

    #[error(transparent)]
    Util(#[from] UtilError),

    #[error(transparent)]
    VDrive(#[from] VirtualDriveError),

    #[error(transparent)]
    CloudInit(#[from] CloudInitError),

    #[error(transparent)]
    ImageStore(#[from] ImageStoreError),
}
