#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ReadMode {
    Short,
    Long,
    Hybrid,
}

#[derive(Clone, Copy, Debug, Default)]
pub struct ModeFeatures {
    pub read_len_p50: usize,
    pub read_len_p90: usize,
    pub avg_minimizers: f32,
    pub ungapped_len_p95: usize,
    pub ungapped_mism_p95: usize,
    pub ungapped_id_p90: f32,
    pub chains_per_read: f32,
}

pub fn classify(features: ModeFeatures) -> ReadMode {
    let p50 = features.read_len_p50;
    let p90 = features.read_len_p90;
    let err_rate = if features.ungapped_len_p95 > 0 {
        features.ungapped_mism_p95 as f32 / features.ungapped_len_p95 as f32
    } else {
        0.0
    };

    if p50 <= 300 && p90 <= 400 {
        return ReadMode::Short;
    }
    if p50 <= 400 && p90 >= 1000 {
        return ReadMode::Hybrid;
    }
    if p50 >= 1000 || p90 >= 2000 {
        return ReadMode::Long;
    }
    if err_rate >= 0.1 || (features.avg_minimizers > 0.0 && features.avg_minimizers < 5.0) {
        return ReadMode::Long;
    }

    if features.chains_per_read >= 5.0 && p90 <= 500 {
        return ReadMode::Short;
    }

    ReadMode::Hybrid
}

use crate::pipeline::PipelineConfig;

#[derive(Clone, Debug)]
pub struct ReadModeProfiles {
    pub short: PipelineConfig,
    pub long: PipelineConfig,
    pub hybrid: PipelineConfig,
    pub decided: Option<ReadMode>,
}

impl ReadModeProfiles {
    pub fn select(&self, mode: ReadMode) -> PipelineConfig {
        match mode {
            ReadMode::Short => self.short,
            ReadMode::Long => self.long,
            ReadMode::Hybrid => self.hybrid,
        }
    }
}
