use anyhow::{Result, bail};
use clap::{Parser, ValueEnum};
use rsfgsea::prelude::*;
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(
    author,
    version,
    about = "Write a single-pathway enrichment plot as PNG"
)]
struct Args {
    #[arg(short, long)]
    ranks: PathBuf,

    #[arg(short, long)]
    gmt: PathBuf,

    #[arg(short, long)]
    pathway: String,

    #[arg(short, long)]
    output: PathBuf,

    #[arg(
        long = "scoreType",
        visible_alias = "score-type",
        value_enum,
        default_value_t = ScoreTypeArg::Std
    )]
    score_type: ScoreTypeArg,

    #[arg(
        long = "gseaParam",
        visible_alias = "gsea-param",
        default_value_t = 1.0
    )]
    gsea_param: f64,

    #[arg(long = "width-in", visible_alias = "width", default_value_t = 3.0)]
    width_inches: f64,

    #[arg(long = "height-in", visible_alias = "height", default_value_t = 2.2)]
    height_inches: f64,

    #[arg(long, default_value_t = 300)]
    dpi: u32,

    #[arg(long, default_value_t = false)]
    transparent_background: bool,

    #[arg(long)]
    title: Option<String>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
enum ScoreTypeArg {
    Std,
    Pos,
    Neg,
}

impl From<ScoreTypeArg> for ScoreType {
    fn from(value: ScoreTypeArg) -> Self {
        match value {
            ScoreTypeArg::Std => ScoreType::Std,
            ScoreTypeArg::Pos => ScoreType::Pos,
            ScoreTypeArg::Neg => ScoreType::Neg,
        }
    }
}

fn main() -> Result<()> {
    let args = Args::parse();
    let ranks = read_ranked_list(&args.ranks)?;
    let pathways = read_gmt(&args.gmt)?;
    let pathway = pathways
        .pathways
        .iter()
        .find(|pw| pw.name == args.pathway)
        .cloned()
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Pathway '{}' was not found in {}",
                args.pathway,
                args.gmt.display()
            )
        })?;

    if args.gsea_param < 0.0 || !args.gsea_param.is_finite() {
        bail!("--gseaParam must be finite and >= 0.");
    }

    write_enrichment_plot_png(
        &ranks,
        &pathway,
        &args.output,
        args.score_type.into(),
        args.gsea_param,
        &EnrichmentPlotOptions {
            width_inches: args.width_inches,
            height_inches: args.height_inches,
            dpi: args.dpi,
            transparent_background: args.transparent_background,
            title: args.title,
        },
    )?;

    Ok(())
}
