use std::cmp::Reverse;

use super::Outcome;
use crate::utils::is_stop_char;
use crate::core::{LowercaseText, FilterList};
use crate::{Lang, Script};

<% alphabets.each do |code, alphabet| -%>
const <%= code.upcase %>: &str = "<%= alphabet %>";
<% end %>

fn get_lang_chars(lang: Lang) -> Vec<char> {
    let alphabet = match lang {
        <% alphabets.keys.each do |code| -%>
        Lang::<%= code.capitalize %> => <%= code.upcase %>,
        <% end %>
        _ => panic!(format!("No alphabet for {}", lang)),
    };
    alphabet.chars().collect()
}

pub fn alphabet_calculate_scores(text: &str) -> Outcome {
    let text = text.to_lowercase();

    let mut raw_scores = vec![
        <% alphabets.keys.each do |code| -%>
        (Lang::<%= code.capitalize %>, 0i32),
        <% end %>
    ];

    let max_raw_score = text.chars().filter(|&ch| !is_stop_char(ch)).count();

    for (lang, score) in &mut raw_scores {
        let alphabet = get_lang_chars(*lang);

        for ch in text.chars() {
            if is_stop_char(ch) {
                continue;
            };
            if alphabet.contains(&ch) {
                *score += 1;
            } else {
                *score -= 1;
            }
        }
    }

    raw_scores.sort_unstable_by_key(|(_, score)| Reverse(*score));

    let raw_scores: Vec<(Lang, usize)> = raw_scores
        .into_iter()
        .map(|(l, s)| {
            let score = if s < 0 { 0usize } else { s as usize };
            (l, score)
        })
        .collect();

    let mut normalized_scores = vec![];

    for &(lang, raw_score) in &raw_scores {
        let normalized_score = raw_score as f64 / max_raw_score as f64;
        normalized_scores.push((lang, normalized_score));
    }

    Outcome {
        max_raw_score,
        raw_scores,
        normalized_scores,
    }
}
