// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::Writeable;
use core::cmp::Ordering;
use core::fmt;

struct WriteComparator<'a> {
    code_units: &'a [u8],
    result: Ordering,
}

/// This is an infallible impl. Functions always return Ok, not Err.
impl fmt::Write for WriteComparator<'_> {
    #[inline]
    fn write_str(&mut self, other: &str) -> fmt::Result {
        if self.result != Ordering::Equal {
            return Ok(());
        }
        let cmp_len = core::cmp::min(other.len(), self.code_units.len());
        let (this, remainder) = self.code_units.split_at(cmp_len);
        self.code_units = remainder;
        self.result = this.cmp(other.as_bytes());
        Ok(())
    }
}

impl<'a> WriteComparator<'a> {
    #[inline]
    fn new(code_units: &'a [u8]) -> Self {
        Self {
            code_units,
            result: Ordering::Equal,
        }
    }

    #[inline]
    fn finish(self) -> Ordering {
        if matches!(self.result, Ordering::Equal) && !self.code_units.is_empty() {
            // Self is longer than Other
            Ordering::Greater
        } else {
            self.result
        }
    }
}

/// Compares the contents of a [`Writeable`] to the given UTF-8 bytes without allocating memory.
///
/// For more details, see: [`cmp_str`]
pub fn cmp_utf8(writeable: &impl Writeable, other: &[u8]) -> Ordering {
    let mut wc = WriteComparator::new(other);
    let _ = writeable.write_to(&mut wc);
    wc.finish().reverse()
}

/// Compares the contents of a `Writeable` to the given bytes
/// without allocating a String to hold the `Writeable` contents.
///
/// This returns a lexicographical comparison, the same as if the Writeable
/// were first converted to a String and then compared with `Ord`. For a
/// string ordering suitable for display to end users, use a localized
/// collation crate, such as `icu_collator`.
///
/// # Examples
///
/// ```
/// use core::cmp::Ordering;
/// use core::fmt;
/// use writeable::Writeable;
///
/// struct WelcomeMessage<'s> {
///     pub name: &'s str,
/// }
///
/// impl<'s> Writeable for WelcomeMessage<'s> {
///     // see impl in Writeable docs
/// #    fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
/// #        sink.write_str("Hello, ")?;
/// #        sink.write_str(self.name)?;
/// #        sink.write_char('!')?;
/// #        Ok(())
/// #    }
/// }
///
/// let message = WelcomeMessage { name: "Alice" };
/// let message_str = message.write_to_string();
///
/// assert_eq!(Ordering::Equal, writeable::cmp_str(&message, "Hello, Alice!"));
///
/// assert_eq!(Ordering::Greater, writeable::cmp_str(&message, "Alice!"));
/// assert_eq!(Ordering::Greater, (*message_str).cmp("Alice!"));
///
/// assert_eq!(Ordering::Less, writeable::cmp_str(&message, "Hello, Bob!"));
/// assert_eq!(Ordering::Less, (*message_str).cmp("Hello, Bob!"));
/// ```
#[inline]
pub fn cmp_str(writeable: &impl Writeable, other: &str) -> Ordering {
    cmp_utf8(writeable, other.as_bytes())
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::fmt::Write;

    mod data {
        include!("../tests/data/data.rs");
    }

    #[test]
    fn test_write_char() {
        for a in data::KEBAB_CASE_STRINGS {
            for b in data::KEBAB_CASE_STRINGS {
                let mut wc = WriteComparator::new(a.as_bytes());
                for ch in b.chars() {
                    wc.write_char(ch).unwrap();
                }
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
            }
        }
    }

    #[test]
    fn test_write_str() {
        for a in data::KEBAB_CASE_STRINGS {
            for b in data::KEBAB_CASE_STRINGS {
                let mut wc = WriteComparator::new(a.as_bytes());
                wc.write_str(b).unwrap();
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
            }
        }
    }

    #[test]
    fn test_mixed() {
        for a in data::KEBAB_CASE_STRINGS {
            for b in data::KEBAB_CASE_STRINGS {
                let mut wc = WriteComparator::new(a.as_bytes());
                let mut first = true;
                for substr in b.split('-') {
                    if first {
                        first = false;
                    } else {
                        wc.write_char('-').unwrap();
                    }
                    wc.write_str(substr).unwrap();
                }
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
            }
        }
    }
}
