use crate::error::Result;
use serde::Deserialize;
use std::env;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};

#[derive(Deserialize, Debug)]
pub struct CargoManifest {
    pub package: Option<CargoPackage>,
}

#[derive(Deserialize, Debug)]
pub struct CargoPackage {
    #[serde(rename = "default-run")]
    pub default_run: Option<String>,
}

pub fn parse(manifest_path: Option<&Path>) -> Result<CargoManifest> {
    let manifest_path = find_cargo_manifest(manifest_path)?;
    let content = fs_err::read_to_string(manifest_path)?;
    let cargo_manifest: CargoManifest = toml::from_str(&content)?;
    Ok(cargo_manifest)
}

fn find_cargo_manifest(manifest_path: Option<&Path>) -> io::Result<PathBuf> {
    if let Some(manifest_path) = manifest_path {
        return Ok(manifest_path.to_owned());
    }

    let dir = env::current_dir()?;
    let mut dir = dir.as_path();
    loop {
        let path = dir.join("Cargo.toml");
        if path.try_exists()? {
            return Ok(path);
        }
        dir = match dir.parent() {
            Some(parent) => parent,
            None => return Err(io::Error::new(ErrorKind::NotFound, "Cargo.toml not found")),
        };
    }
}
