use pulldown_cmark::{CowStr, Event, Tag};
use std::iter::Peekable;

pub struct FootnoteBackrefs<'a, I: Iterator<Item = Event<'a>>> {
    iter: Peekable<I>,
    next: Option<Event<'a>>,
}

pub fn new<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> FootnoteBackrefs<'a, I> {
    FootnoteBackrefs {
        iter: iter.peekable(),
        next: None,
    }
}

impl<'a, I: Iterator<Item = Event<'a>>> Iterator for FootnoteBackrefs<'a, I> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(e) = self.next.take() {
            return Some(e);
        }

        match self.iter.next() {
            Some(Event::FootnoteReference(label)) => {
                let html = format!(
                    r##"<sup class="footnote-reference" id="fnref{}"><a href="#{}">[{}]</a></sup>"##,
                    label, label, label
                );
                Some(Event::Html(CowStr::Boxed(html.into_boxed_str())))
            }
            Some(Event::End(Tag::Paragraph)) => {
                if let Some(Event::End(Tag::FootnoteDefinition(label))) = self.iter.peek() {
                    assert!(self.next.is_none());
                    self.next = Some(Event::End(Tag::Paragraph));
                    let html = format!(
                        r##" <a href="#fnref{}" class="footnote-backref">↩</a>"##,
                        label
                    );
                    Some(Event::Html(CowStr::Boxed(html.into_boxed_str())))
                } else {
                    Some(Event::End(Tag::Paragraph))
                }
            }
            e => e,
        }
    }
}

#[cfg(test)]
mod tests {
    use pulldown_cmark::{html, Options, Parser};

    fn render(s: &str) -> String {
        let mut out = String::new();
        let parser = Parser::new_ext(s, Options::ENABLE_FOOTNOTES);
        let footnote_backrefs = super::new(parser);
        html::push_html(&mut out, footnote_backrefs);
        out
    }

    #[test]
    fn test_footnote_backrefs() {
        assert_eq!(
            render("foo[^1]\n\n[^1]: bar"),
            r##"<p>foo<sup class="footnote-reference" id="fnref1"><a href="#1">[1]</a></sup></p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>bar <a href="#fnref1" class="footnote-backref">↩</a></p>
</div>
"##
        );
    }
}
