package Classy::Dialect::SpanParser;

use strict;
use warnings;
use namespace::autoclean;

our $VERSION = '0.10';

use Markdent::Event::StartHTMLTag;
use Markdent::Event::EndHTMLTag;
use Markdent::Event::HTMLTag;
use Markdent::Event::StartOrderedList;
use Markdent::Event::EndOrderedList;
use Markdent::Event::HorizontalRule;
use Markdent::Event::StartLink;
use Markdent::Event::EndLink;
use Markdent::Event::Text;
use Markdent::Types;

use Moose::Role;

with 'Markdent::Dialect::GitHub::SpanParser';

has _notes_by_id => (
    traits   => ['Hash'],
    is       => 'ro',
    isa      => t( 'HashRef', of => t('Str') ),
    default  => sub { {} },
    init_arg => undef,
    handles  => {
        _add_fn_by_id => 'set',
        _get_fn_by_id => 'get',
        _reset_footnotes => 'clear',
    },
);

has _note_idx_map => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => t( 'ArrayRef', of => t('Str') ),
    default  => sub { [] },
    handles  => {
        _add_fn_to_map => 'push',
        _get_fn_list => 'get',
        _fn_list_count => 'count',
        _reset_fn_map => 'clear',
    },
);

# Footnotes are kinda like links, but IDs are prefixed with a caret (^)
around extract_link_ids => sub {
    my $orig = shift;
    my $self = shift;
    my $text = shift;

    ${$text} =~ s/ ^
                   \p{SpaceSeparator}{0,3}
                   \[ \^ ([^]]+) \]
                   :
                   \p{SpaceSeparator}*
                   \n?
                   \p{SpaceSeparator}*
                   (
                       (.|\n[^\n])+
                   )
                   (?:\n\n|$)
                 /
                    $self->_process_id_for_fn( $1, $2 );
                    ''
                 /egxm;
    $self->$orig($text);
};

around _possible_span_matches => sub {
    my $orig = shift;
    my $self = shift;
    my @look_for = $self->$orig();

    unshift @look_for, 'footnote';

    return @look_for;
};

sub _process_id_for_fn {
    my $self = shift;
    my $id = shift;
    my $id_text = shift;

    $id_text =~ s/\s+$//;
    $id_text =~ s/\n+/ /g;
    $self->_debug_parse_result(
        $id,
        'footnote',
        [ text => $id_text ],
    ) if $self->debug;

    $self->_add_fn_by_id( $id => $id_text );
}

# Matches the inline footnote
sub _match_footnote {
    my $self = shift;
    my $text = shift;

    my $pos = pos ${$text} || 0;

    return
        unless ${$text} =~ / \G
                             \[ \^ ([^]]+) \] # footnote id
                           /xgc;

    my $fn_id = $1;

    $self->_add_fn_to_map($fn_id);
    my $fn_idx = $self->_fn_list_count;

    # <sup>[<a href="#fn:id" title="fnref:id">idx</a>]</sup>
    my $start_sup = $self->_make_event( StartHTMLTag => { tag => "sup" });
    my $start_brack = '[';
    my $end_brack = ']';
    my $end_sup = $self->_make_event( EndHTMLTag => { tag => "sup" });
    my $start_link = $self->_make_event( StartHTMLTag => {
            tag => 'a',
            attributes => {
                href => "#fn:$fn_id",
                id => "fnref:$fn_id",
            },
    });
    my $end_link = $self->_make_event('EndLink');

    $self->_markup_event($start_sup);
    $self->_parse_text( \$start_brack );
    $self->_markup_event($start_link);
    $self->_parse_text( \$fn_idx );
    $self->_markup_event($end_link);
    $self->_parse_text( \$end_brack );
    $self->_markup_event($end_sup);

    return 1;
}

1;

__END__