use nom::{IResult, Parser, branch::alt, bytes::complete::tag, sequence::terminated};

use crate::{
    ast::{Inline, LinkReference},
    parser::link_util::link_label,
};

pub(super) fn reference_link<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Inline> {
    move |input: &'a str| {
        alt((
            reference_link_full(),
            reference_link_collapsed(),
            reference_link_shortcut(),
        ))
        .parse(input)
    }
}

pub(super) fn reference_link_full<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Inline> {
    move |input: &'a str| {
        let (input, (text, label)) = (link_label(), link_label()).parse(input)?;
        let link_reference = LinkReference { label, text };
        Ok((input, Inline::LinkReference(link_reference)))
    }
}

pub(super) fn reference_link_collapsed<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Inline> {
    move |input: &'a str| {
        let (input, text) = terminated(link_label(), tag("[]")).parse(input)?;
        let link_reference = LinkReference {
            label: text.clone(),
            text,
        };
        Ok((input, Inline::LinkReference(link_reference)))
    }
}

pub(super) fn reference_link_shortcut<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Inline> {
    move |input: &'a str| {
        let (input, text) = link_label().parse(input)?;
        let link_reference = LinkReference {
            label: text.clone(),
            text,
        };
        Ok((input, Inline::LinkReference(link_reference)))
    }
}
