use crate::parser::{FromData, LazyArray32, Offset, Offset32, Stream, U24};
use crate::GlyphId;
#[derive(Clone, Copy)]
struct VariationSelectorRecord {
    var_selector: u32,
    default_uvs_offset: Option<Offset32>,
    non_default_uvs_offset: Option<Offset32>,
}
impl FromData for VariationSelectorRecord {
    const SIZE: usize = 11;
    #[inline]
    fn parse(data: &[u8]) -> Option<Self> {
        let mut s = Stream::new(data);
        Some(VariationSelectorRecord {
            var_selector: s.read::<U24>()?.0,
            default_uvs_offset: s.read::<Option<Offset32>>()?,
            non_default_uvs_offset: s.read::<Option<Offset32>>()?,
        })
    }
}
#[derive(Clone, Copy)]
struct UVSMappingRecord {
    unicode_value: u32,
    glyph_id: GlyphId,
}
impl FromData for UVSMappingRecord {
    const SIZE: usize = 5;
    #[inline]
    fn parse(data: &[u8]) -> Option<Self> {
        let mut s = Stream::new(data);
        Some(UVSMappingRecord {
            unicode_value: s.read::<U24>()?.0,
            glyph_id: s.read::<GlyphId>()?,
        })
    }
}
#[derive(Clone, Copy)]
struct UnicodeRangeRecord {
    start_unicode_value: u32,
    additional_count: u8,
}
impl UnicodeRangeRecord {
    fn contains(&self, c: u32) -> bool {
        let end = self.start_unicode_value + u32::from(self.additional_count);
        (self.start_unicode_value..=end).contains(&c)
    }
}
impl FromData for UnicodeRangeRecord {
    const SIZE: usize = 4;
    #[inline]
    fn parse(data: &[u8]) -> Option<Self> {
        let mut s = Stream::new(data);
        Some(UnicodeRangeRecord {
            start_unicode_value: s.read::<U24>()?.0,
            additional_count: s.read::<u8>()?,
        })
    }
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum GlyphVariationResult {
    Found(GlyphId),
    UseDefault,
}
#[derive(Clone, Copy)]
pub struct Subtable14<'a> {
    records: LazyArray32<'a, VariationSelectorRecord>,
    data: &'a [u8],
}
impl<'a> Subtable14<'a> {
    pub fn parse(data: &'a [u8]) -> Option<Self> {
        let mut s = Stream::new(data);
        s.skip::<u16>(); s.skip::<u32>(); let count = s.read::<u32>()?;
        let records = s.read_array32::<VariationSelectorRecord>(count)?;
        Some(Self { records, data })
    }
    pub fn glyph_index(&self, code_point: u32, variation: u32) -> Option<GlyphVariationResult> {
        let (_, record) = self
            .records
            .binary_search_by(|v| v.var_selector.cmp(&variation))?;
        if let Some(offset) = record.default_uvs_offset {
            let data = self.data.get(offset.to_usize()..)?;
            let mut s = Stream::new(data);
            let count = s.read::<u32>()?;
            let ranges = s.read_array32::<UnicodeRangeRecord>(count)?;
            for range in ranges {
                if range.contains(code_point) {
                    return Some(GlyphVariationResult::UseDefault);
                }
            }
        }
        if let Some(offset) = record.non_default_uvs_offset {
            let data = self.data.get(offset.to_usize()..)?;
            let mut s = Stream::new(data);
            let count = s.read::<u32>()?;
            let uvs_mappings = s.read_array32::<UVSMappingRecord>(count)?;
            let (_, mapping) =
                uvs_mappings.binary_search_by(|v| v.unicode_value.cmp(&code_point))?;
            return Some(GlyphVariationResult::Found(mapping.glyph_id));
        }
        None
    }
}
impl core::fmt::Debug for Subtable14<'_> {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(f, "Subtable14 {{ ... }}")
    }
}