use super::macros::to_ast_node;
use crate::types::AngleLink;
use crate::types::BabelCall;
use crate::types::Bold;
use crate::types::Citation;
use crate::types::CitationReference;
use crate::types::Clock;
use crate::types::Code;
use crate::types::Comment;
use crate::types::CommentBlock;
use crate::types::DiarySexp;
use crate::types::Document;
use crate::types::DocumentElement;
use crate::types::Drawer;
use crate::types::DynamicBlock;
use crate::types::Element;
use crate::types::Entity;
use crate::types::ExampleBlock;
use crate::types::ExportBlock;
use crate::types::ExportSnippet;
use crate::types::FixedWidthArea;
use crate::types::FootnoteDefinition;
use crate::types::FootnoteReference;
use crate::types::GreaterBlock;
use crate::types::Heading;
use crate::types::HorizontalRule;
use crate::types::InlineBabelCall;
use crate::types::InlineSourceBlock;
use crate::types::Italic;
use crate::types::Keyword;
use crate::types::LatexEnvironment;
use crate::types::LatexFragment;
use crate::types::LineBreak;
use crate::types::Object;
use crate::types::OrgMacro;
use crate::types::Paragraph;
use crate::types::PlainLink;
use crate::types::PlainList;
use crate::types::PlainListItem;
use crate::types::PlainText;
use crate::types::Planning;
use crate::types::PropertyDrawer;
use crate::types::RadioLink;
use crate::types::RadioTarget;
use crate::types::RegularLink;
use crate::types::Section;
use crate::types::SrcBlock;
use crate::types::StatisticsCookie;
use crate::types::StrikeThrough;
use crate::types::Subscript;
use crate::types::Superscript;
use crate::types::Table;
use crate::types::Target;
use crate::types::Timestamp;
use crate::types::Underline;
use crate::types::Verbatim;
use crate::types::VerseBlock;

pub enum AstNode<'r, 's> {
    // Document Nodes
    Document(&'r Document<'s>),
    Heading(&'r Heading<'s>),
    Section(&'r Section<'s>),
    // Elements
    Paragraph(&'r Paragraph<'s>),
    PlainList(&'r PlainList<'s>),
    PlainListItem(&'r PlainListItem<'s>),
    GreaterBlock(&'r GreaterBlock<'s>),
    DynamicBlock(&'r DynamicBlock<'s>),
    FootnoteDefinition(&'r FootnoteDefinition<'s>),
    Comment(&'r Comment<'s>),
    Drawer(&'r Drawer<'s>),
    PropertyDrawer(&'r PropertyDrawer<'s>),
    Table(&'r Table<'s>),
    VerseBlock(&'r VerseBlock<'s>),
    CommentBlock(&'r CommentBlock<'s>),
    ExampleBlock(&'r ExampleBlock<'s>),
    ExportBlock(&'r ExportBlock<'s>),
    SrcBlock(&'r SrcBlock<'s>),
    Clock(&'r Clock<'s>),
    DiarySexp(&'r DiarySexp<'s>),
    Planning(&'r Planning<'s>),
    FixedWidthArea(&'r FixedWidthArea<'s>),
    HorizontalRule(&'r HorizontalRule<'s>),
    Keyword(&'r Keyword<'s>),
    BabelCall(&'r BabelCall<'s>),
    LatexEnvironment(&'r LatexEnvironment<'s>),
    // Objects
    Bold(&'r Bold<'s>),
    Italic(&'r Italic<'s>),
    Underline(&'r Underline<'s>),
    StrikeThrough(&'r StrikeThrough<'s>),
    Code(&'r Code<'s>),
    Verbatim(&'r Verbatim<'s>),
    PlainText(&'r PlainText<'s>),
    RegularLink(&'r RegularLink<'s>),
    RadioLink(&'r RadioLink<'s>),
    RadioTarget(&'r RadioTarget<'s>),
    PlainLink(&'r PlainLink<'s>),
    AngleLink(&'r AngleLink<'s>),
    OrgMacro(&'r OrgMacro<'s>),
    Entity(&'r Entity<'s>),
    LatexFragment(&'r LatexFragment<'s>),
    ExportSnippet(&'r ExportSnippet<'s>),
    FootnoteReference(&'r FootnoteReference<'s>),
    Citation(&'r Citation<'s>),
    CitationReference(&'r CitationReference<'s>),
    InlineBabelCall(&'r InlineBabelCall<'s>),
    InlineSourceBlock(&'r InlineSourceBlock<'s>),
    LineBreak(&'r LineBreak<'s>),
    Target(&'r Target<'s>),
    StatisticsCookie(&'r StatisticsCookie<'s>),
    Subscript(&'r Subscript<'s>),
    Superscript(&'r Superscript<'s>),
    Timestamp(&'r Timestamp<'s>),
}

impl<'r, 's> From<&'r DocumentElement<'s>> for AstNode<'r, 's> {
    fn from(value: &'r DocumentElement<'s>) -> Self {
        match value {
            DocumentElement::Heading(inner) => inner.into(),
            DocumentElement::Section(inner) => inner.into(),
        }
    }
}

impl<'r, 's> From<&'r Element<'s>> for AstNode<'r, 's> {
    fn from(value: &'r Element<'s>) -> Self {
        match value {
            Element::Paragraph(inner) => inner.into(),
            Element::PlainList(inner) => inner.into(),
            Element::GreaterBlock(inner) => inner.into(),
            Element::DynamicBlock(inner) => inner.into(),
            Element::FootnoteDefinition(inner) => inner.into(),
            Element::Comment(inner) => inner.into(),
            Element::Drawer(inner) => inner.into(),
            Element::PropertyDrawer(inner) => inner.into(),
            Element::Table(inner) => inner.into(),
            Element::VerseBlock(inner) => inner.into(),
            Element::CommentBlock(inner) => inner.into(),
            Element::ExampleBlock(inner) => inner.into(),
            Element::ExportBlock(inner) => inner.into(),
            Element::SrcBlock(inner) => inner.into(),
            Element::Clock(inner) => inner.into(),
            Element::DiarySexp(inner) => inner.into(),
            Element::Planning(inner) => inner.into(),
            Element::FixedWidthArea(inner) => inner.into(),
            Element::HorizontalRule(inner) => inner.into(),
            Element::Keyword(inner) => inner.into(),
            Element::BabelCall(inner) => inner.into(),
            Element::LatexEnvironment(inner) => inner.into(),
        }
    }
}

impl<'r, 's> From<&'r Object<'s>> for AstNode<'r, 's> {
    fn from(value: &'r Object<'s>) -> Self {
        match value {
            Object::Bold(inner) => inner.into(),
            Object::Italic(inner) => inner.into(),
            Object::Underline(inner) => inner.into(),
            Object::StrikeThrough(inner) => inner.into(),
            Object::Code(inner) => inner.into(),
            Object::Verbatim(inner) => inner.into(),
            Object::PlainText(inner) => inner.into(),
            Object::RegularLink(inner) => inner.into(),
            Object::RadioLink(inner) => inner.into(),
            Object::RadioTarget(inner) => inner.into(),
            Object::PlainLink(inner) => inner.into(),
            Object::AngleLink(inner) => inner.into(),
            Object::OrgMacro(inner) => inner.into(),
            Object::Entity(inner) => inner.into(),
            Object::LatexFragment(inner) => inner.into(),
            Object::ExportSnippet(inner) => inner.into(),
            Object::FootnoteReference(inner) => inner.into(),
            Object::Citation(inner) => inner.into(),
            Object::CitationReference(inner) => inner.into(),
            Object::InlineBabelCall(inner) => inner.into(),
            Object::InlineSourceBlock(inner) => inner.into(),
            Object::LineBreak(inner) => inner.into(),
            Object::Target(inner) => inner.into(),
            Object::StatisticsCookie(inner) => inner.into(),
            Object::Subscript(inner) => inner.into(),
            Object::Superscript(inner) => inner.into(),
            Object::Timestamp(inner) => inner.into(),
        }
    }
}

to_ast_node!(&'r Document<'s>, AstNode::Document);
to_ast_node!(&'r Heading<'s>, AstNode::Heading);
to_ast_node!(&'r Section<'s>, AstNode::Section);
to_ast_node!(&'r Paragraph<'s>, AstNode::Paragraph);
to_ast_node!(&'r PlainList<'s>, AstNode::PlainList);
to_ast_node!(&'r PlainListItem<'s>, AstNode::PlainListItem);
to_ast_node!(&'r GreaterBlock<'s>, AstNode::GreaterBlock);
to_ast_node!(&'r DynamicBlock<'s>, AstNode::DynamicBlock);
to_ast_node!(&'r FootnoteDefinition<'s>, AstNode::FootnoteDefinition);
to_ast_node!(&'r Comment<'s>, AstNode::Comment);
to_ast_node!(&'r Drawer<'s>, AstNode::Drawer);
to_ast_node!(&'r PropertyDrawer<'s>, AstNode::PropertyDrawer);
to_ast_node!(&'r Table<'s>, AstNode::Table);
to_ast_node!(&'r VerseBlock<'s>, AstNode::VerseBlock);
to_ast_node!(&'r CommentBlock<'s>, AstNode::CommentBlock);
to_ast_node!(&'r ExampleBlock<'s>, AstNode::ExampleBlock);
to_ast_node!(&'r ExportBlock<'s>, AstNode::ExportBlock);
to_ast_node!(&'r SrcBlock<'s>, AstNode::SrcBlock);
to_ast_node!(&'r Clock<'s>, AstNode::Clock);
to_ast_node!(&'r DiarySexp<'s>, AstNode::DiarySexp);
to_ast_node!(&'r Planning<'s>, AstNode::Planning);
to_ast_node!(&'r FixedWidthArea<'s>, AstNode::FixedWidthArea);
to_ast_node!(&'r HorizontalRule<'s>, AstNode::HorizontalRule);
to_ast_node!(&'r Keyword<'s>, AstNode::Keyword);
to_ast_node!(&'r BabelCall<'s>, AstNode::BabelCall);
to_ast_node!(&'r LatexEnvironment<'s>, AstNode::LatexEnvironment);
to_ast_node!(&'r Bold<'s>, AstNode::Bold);
to_ast_node!(&'r Italic<'s>, AstNode::Italic);
to_ast_node!(&'r Underline<'s>, AstNode::Underline);
to_ast_node!(&'r StrikeThrough<'s>, AstNode::StrikeThrough);
to_ast_node!(&'r Code<'s>, AstNode::Code);
to_ast_node!(&'r Verbatim<'s>, AstNode::Verbatim);
to_ast_node!(&'r PlainText<'s>, AstNode::PlainText);
to_ast_node!(&'r RegularLink<'s>, AstNode::RegularLink);
to_ast_node!(&'r RadioLink<'s>, AstNode::RadioLink);
to_ast_node!(&'r RadioTarget<'s>, AstNode::RadioTarget);
to_ast_node!(&'r PlainLink<'s>, AstNode::PlainLink);
to_ast_node!(&'r AngleLink<'s>, AstNode::AngleLink);
to_ast_node!(&'r OrgMacro<'s>, AstNode::OrgMacro);
to_ast_node!(&'r Entity<'s>, AstNode::Entity);
to_ast_node!(&'r LatexFragment<'s>, AstNode::LatexFragment);
to_ast_node!(&'r ExportSnippet<'s>, AstNode::ExportSnippet);
to_ast_node!(&'r FootnoteReference<'s>, AstNode::FootnoteReference);
to_ast_node!(&'r Citation<'s>, AstNode::Citation);
to_ast_node!(&'r CitationReference<'s>, AstNode::CitationReference);
to_ast_node!(&'r InlineBabelCall<'s>, AstNode::InlineBabelCall);
to_ast_node!(&'r InlineSourceBlock<'s>, AstNode::InlineSourceBlock);
to_ast_node!(&'r LineBreak<'s>, AstNode::LineBreak);
to_ast_node!(&'r Target<'s>, AstNode::Target);
to_ast_node!(&'r StatisticsCookie<'s>, AstNode::StatisticsCookie);
to_ast_node!(&'r Subscript<'s>, AstNode::Subscript);
to_ast_node!(&'r Superscript<'s>, AstNode::Superscript);
to_ast_node!(&'r Timestamp<'s>, AstNode::Timestamp);