package Silki::Markdent::Dialect::Silki::SpanParser;
BEGIN {
  $Silki::Markdent::Dialect::Silki::SpanParser::VERSION = '0.09';
}

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

use List::AllUtils qw( insert_after_string );
use Silki::Markdent::Event::FileLink;
use Silki::Markdent::Event::ImageLink;
use Silki::Markdent::Event::WikiLink;

use Moose;
use MooseX::SemiAffordanceAccessor;
use MooseX::StrictConstructor;

extends 'Markdent::Dialect::Theory::SpanParser';

sub _possible_span_matches {
    my $self = shift;

    my @look_for = $self->SUPER::_possible_span_matches(@_);

    # inside code span
    return @look_for if @look_for == 1;

    for my $val (qw( image_link file_link wiki_link )) {
        insert_after_string 'code_start', $val, @look_for;
    }

    return @look_for;
}

# More or less stolen from Text::Markdown
my $nested_brackets;
$nested_brackets = qr{
    (?>                                 # Atomic matching
       [^\[\]]+                           # Anything other than brackets
       |
       \[
         (??{ $nested_brackets })        # Recursive set of nested curlies
       \]
    )*
}x;

sub _match_wiki_link {
    my $self = shift;
    my $text = shift;

    return unless ${$text} =~ / \G
                                (?:
                                  \[
                                  ($nested_brackets)
                                  \]
                                )?
                                \(\(
                                (.+?)
                                \)\)
                              /xmgc;

    my %p = ( link_text => $2 );
    $p{display_text} = $1
        if defined $1;

    my $event = $self->_make_event( 'Silki::Markdent::Event::WikiLink' => %p );

    $self->_markup_event($event);

    return 1;
}

sub _match_file_link {
    my $self = shift;
    my $text = shift;


    return unless ${$text} =~ / \G
                                (?:
                                  \[
                                  ($nested_brackets)
                                  \]
                                )?
                                {{
                                \s*
                                file:
                                \s*
                                ([^}]+)
                                \s*
                                }}
                              /xmgc;

    my %p = ( link_text => $2 );
    $p{display_text} = $1 if defined $1;

    my $event = $self->_make_event( 'Silki::Markdent::Event::FileLink' => %p );

    $self->_markup_event($event);

    return 1;
}

sub _match_image_link {
    my $self = shift;
    my $text = shift;

    return unless ${$text} =~ / \G
                                {{
                                \s*
                                image:
                                \s*
                                ([^}]+)
                                \s*
                                }}
                              /xmgc;

    my %p = ( link_text => $1 );

    my $event = $self->_make_event( 'Silki::Markdent::Event::ImageLink' => %p );

    $self->_markup_event($event);

    return 1;
}

sub _match_plain_text {
    my $self = shift;
    my $text = shift;

    my $escape_re = $self->_escape_re();

    # Note that we're careful not to consume any of the characters marking the
    # (possible) end of the plain text. If those things turn out to _not_ be
    # markup, we'll get them on the next pass, because we always match at
    # least one character, so we should never get stuck in a loop.
    return unless
        ${$text} =~ /\G
                     ( .+? )              # at least one character followed by ...
                     (?=
                       $escape_re
                       |
                       \*                 #   possible span markup
                       |
                       _
                       |
                       \p{SpaceSeparator}* \`
                       |
                       \(\(               #   possible wiki link
                       |
                       \{\{               #   possible wiki command
                       |
                       !?\[               #   possible image or link
                       |
                       < [^>]+ >          #   an HTML tag
                       |
                       &\S+;              #   an HTML entity
                       |
                       \z                 #   or the end of the string
                     )
                    /xgcs;

    $self->_print_debug( "Interpreting as plain text\n\n[$1]\n" )
        if $self->debug();

    $self->_save_span_text($1);

    return 1;
}

__PACKAGE__->meta()->make_immutable();

1;

# ABSTRACT: Parses span-level markup for the Silki Markdown dialect

__END__
=pod

=head1 NAME

Silki::Markdent::Dialect::Silki::SpanParser - Parses span-level markup for the Silki Markdown dialect

=head1 VERSION

version 0.09

=head1 AUTHOR

  Dave Rolsky <autarch@urth.org>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2010 by Dave Rolsky.

This is free software, licensed under:

  The GNU Affero General Public License, Version 3, November 2007

=cut

