Documentation
use std::ops::RangeInclusive;

/// All valid kana for the digest
pub const KANA: &[char; 92] = &[
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '',
    '', //45
    '', '', '', '', '',
    '', '', '', '', '',
    '', '', '', '', '', 
    '', '', '', '', '', 
    '', '', '', '', '', 
    '', '', '', '', '', 
    '', '', '', '', '', 
    '', '', '', '', '', 
    '', '', '', '', '',
    '', //91 
];

/// Valid kana for the first swap table
pub const KANA_SWAP: &[Option<char>; 92] = &[
    None, None, None, None, None, //a
    Some(''), Some(''), Some(''), Some(''), Some(''), //ka
    None, None, None, None, None, //sa
    Some(''), Some(''), Some(''), Some(''), Some(''), //ta
    None, None, None, None, None, //na
    Some(''), Some(''), Some(''), Some(''), Some(''), // ha
    None, None, None, None, None, //ma
    None, None, None, None, None, //ra
    None, None, None, None, None, //ya
    None, //wo (45)
    None, None, None, None, None, //a
    Some(''), Some(''), Some(''), Some(''), Some(''), //ka
    None, None, None, None, None, //sa
    Some(''), Some(''), Some(''), Some(''), Some(''), //ta
    None, None, None, None, None, //na
    Some(''), Some(''), Some(''), Some(''), Some(''), // ha
    None, None, None, None, None, //ma
    None, None, None, None, None, //ra
    None, None, None, None, None, //ya    
    None, //wo (91)
];

/// Valid kana for the 2nd swap table
pub const KANA_SWAP2: &[Option<char>; 92] = &[
    None, None, None, None, None, //a
    None, None, None, None, None, //ka
    None, None, None, None, None, //sa
    None, None, None, None, None, //ta
    None, None, None, None, None, //na
    Some(''), Some(''), Some(''), Some(''), Some(''), //ha
    None, None, None, None, None, //ma
    None, None, None, None, None, //ra
    None, None, None, None, None, //ya
    None, //wo (45)
    None, None, None, None, None, //a
    None, None, None, None, None, //ka
    None, None, None, None, None, //sa
    None, None, None, None, None, //ta
    None, None, None, None, None, //na
    Some(''), Some(''), Some(''), Some(''), Some(''), //ha
    None, None, None, None, None, //ma
    None, None, None, None, None, //ra
    None, None, None, None, None, //ya
    None, //wo (91)
];

/// Ranges for the sign0 test
pub const KANA_SIGN: &[RangeInclusive<usize>; 2] = &[
    0..=45,
    46..=91,
];

/// Valid kana for the subscript
pub const KANA_SUB: &[char; 18] = &[
    '',
    '',
    '',
    '',
    '',
    '',
    '',
    '',
    '','','','','',
    '','','','','',
];

use crate::def::Definition;

/// Valid ranges for the subscript from the kana table
pub const KANA_SUB_VALID_FOR: &[Definition; 18] = &[ // Should we properly restrict these to only ones that make sense? (i.e. KI SHI HI etc..)
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(51..=85),
    Definition::single(51..=85),
    Definition::single(51..=85),
    
    Definition::single(0..=45),
    Definition::single(46..=91),
    
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(5..=39),
    Definition::single(51..=85),
    Definition::single(51..=85),
    Definition::single(51..=85),
    Definition::single(51..=85),
    Definition::single(51..=85),
];

/// Find all subs that are okay for this kana. If `kana` is not in `KANA`, return None.
pub fn find_sub(kana: char) -> Option<Vec<char>>
{
    for (i,x) in (0..(KANA.len())).zip(KANA.iter()) {
	if *x == kana {
	    let mut output = Vec::with_capacity(KANA_SUB.len());
	    for (def,sub) in KANA_SUB_VALID_FOR.iter().zip(KANA_SUB.iter())
	    {
		if def.contains(i) {
		    output.push(sub.clone());
		}
	    }
	    return Some(output);
	}
    }
    None
}

/// Find subs by index.
pub fn sub(i: usize) -> Option<[Option<char>; KANA_SUB.len()]>
{
    if i < KANA.len() {
	let mut output = [None; KANA_SUB.len()];
	for (j, (def,sub)) in (0..).zip(KANA_SUB_VALID_FOR.iter().zip(KANA_SUB.iter()))
	{
	    if def.contains(i) {
		output[j] = Some(sub.clone());
	    }
	}
	Some(output)
    } else {
	None
    }
}

/// Get all valid subs for kana at index `i`.
pub fn sub_all(i: usize) -> Option<Vec<char>>
{
    if i < KANA.len() {
	let mut output = Vec::with_capacity(KANA_SUB.len());
	for (def,sub) in KANA_SUB_VALID_FOR.iter().zip(KANA_SUB.iter())
	{
	    if def.contains(i) {
		output.push(sub.clone());
	    }
	}
	Some(output)
    } else {
	None
    }
}