//! JSX-exclusive parsing — features that have no HTML equivalent.
//!
//! This module acts as a pre-pass called from [`super::parse_input`] before
//! any shared operator detection. It returns `Some(Element)` when the input
//! matches a JSX-specific pattern, or `None` to fall through to the shared
//! parser.
//!
//! ## Conditional rendering
//!
//! The `->` separator triggers conditional rendering output:
//!
//! ```text
//! condition->true_part              →  {condition && <true_part />}
//! condition->true_part->false_part  →  {condition ? <true_part /> : <false_part />}
//! ```
//!
//! `->` is not valid JavaScript syntax, so it is an unambiguous delimiter
//! even when the condition expression contains other operators (`||`, `&&`,
//! arrow functions, etc.).

use crate::{
    config::Config,
    parser::{Element, GlyfError, utils::find_sequence_at_depth_zero},
};

/// Splits a `->` conditional expression into its three components.
///
/// Returns `(condition, true_part, Some(false_part))` for ternary, or
/// `(condition, true_part, None)` for the `&&` short-circuit form.
/// Returns `None` if no `->` is found at depth 0.
fn parse_condition(input: &str) -> Option<(&str, &str, Option<&str>)> {
    let condition_end = find_sequence_at_depth_zero(input, "->")?;
    let condition = &input[..condition_end];
    let rest = &input[condition_end + 2..];
    let else_index = find_sequence_at_depth_zero(rest, "->");
    let true_part = &rest[..else_index.unwrap_or(rest.len())];
    if condition.is_empty() || true_part.is_empty() {
        return None;
    }

    Some((
        condition,
        true_part,
        else_index.map(|index| &rest[index + 2..]),
    ))
}

/// JSX-exclusive pre-pass: tries to match `input` against JSX-only patterns.
///
/// Returns `Some(element)` when a JSX-specific pattern is matched (currently
/// only conditional rendering via `->`).
/// Returns `None` to fall through to the shared HTML+JSX parser.
pub(super) fn try_parse_jsx(
    input: &str,
    level: Option<usize>,
    config: &Config,
) -> Result<Option<Element>, GlyfError> {
    let Some((condition, true_str, false_str)) = parse_condition(input) else {
        return Ok(None);
    };
    Ok(Some(Element::from_condition(
        condition, true_str, false_str, None, level, config,
    )?))
}
