use std::str::FromStr;

use markdown_it::parser::inline::{InlineRule, InlineState};
use markdown_it::{Node, NodeValue, Renderer};
use maud::Render;

use crate::components::fa::FAIcon;

#[derive(Debug)]
pub struct InlineEmote(String);

impl NodeValue for InlineEmote {
	fn render(&self, _node: &Node, fmt: &mut dyn Renderer) {
		fmt.text_raw(self.0.as_str());
	}
}

impl InlineRule for InlineEmote {
	const MARKER: char = ':';

	fn run(state: &mut InlineState<'_, '_>) -> Option<(Node, usize)> {
		let input = &state.src[state.pos..state.pos_max];

		if !input.starts_with(':') {
			return None;
		}

		let end_idx = input[1..].find(':')? + 1;
		let code = &input[1..end_idx];

		let mut emote = None;

		if emote.is_none()
			&& let Some(code) = code.strip_prefix("fa-")
		{
			emote = FAIcon::from_str(code).ok().map(|x| x.render().0)
		}

		if emote.is_none() {
			emote = emojis::get_by_shortcode(code).map(|x| x.to_string());
		}

		Some((Node::new(InlineEmote(emote?)), end_idx + 1))
	}
}
