
package Text::Wigwam::Engine::Totem::Token::Terminator::Explicit;

    use strict; 
    use warnings;
    our $VERSION = '0.01';

    use base q/Text::Wigwam::Cast/;

    use Text::Wigwam::Const( qw/TERM/ );
    use Text::Wigwam::Engine::Totem::Const(
      qw/
        TEXT_BLOCK
        ROOT_BLOCK
        CODE_BLOCK
      /
    );

sub new {
    return bless { MATE => $_[1], DRAW => $_[2] }
}
sub exec {
    my ($tokn, $want, $Arg, $Api, $core) = @_;
     # Associate a terminator token with the appropriate
     # directive type, or ignore the terminator.
    $core->next_token;
#    if(
#         $want & TERM
#      && !($Arg->type & (TEXT_BLOCK | ROOT_BLOCK ))
#    ){
    if( ($want & TERM) && !$Arg->type ){
        if( (my $mate = $Arg->mate) ne $tokn->{MATE} ){
            $Api->exception(
                "Terminator mismatch - expected $mate"
            );
        }
        else {
         # If all's well, optimize
            bless $tokn, 'Text::Wigwam::Engine::Totem::Token::Terminator::Fast'
              if $Api->get_options( qw/strict_tags/ );
        }
        $Arg->end_list(1);
        return;
    }
     # Strict template code enforcement feature
    return $core->curr_token->exec( $want, $Arg, $Api, $core )
        unless $Api->get_options( qw/strict_tags/ );
#    return $Arg->exec($Api)
#      unless $Api->get_options( qw/strict_tags/ );
    $Api->exception(
        "Encountered an unexpected list terminator - expected ".$Arg->mate
    );
    return $Arg->null_data( $want );
}
sub skip {
    my ($tokn, $list, $Arg, $Api, $core) = @_;
    $core->next_token;

    return if $Arg->type & (TEXT_BLOCK);

    if( $list ){
        if( $Arg->mate eq $tokn->{MATE} ){
         # All's well, optimize
            bless $tokn, 'Text::Wigwam::Engine::Totem::Token::Terminator::Fast'
              if $Api->get_options( qw/strict_tags/ );
            return TERM;
        }
        else {
            $Api->exception(
                "Terminator mismatch - expected ". $Arg->mate
            );
        }
        return TERM;
    }
     # Strict tag enforcement feature
    return $core->curr_token->skip( $list, $Arg, $Api, $core )
      unless $Api->get_options( qw/strict_tags/ );
    $Api->exception(
        "Encountered an unexpected list terminator."
    );
    return;
}
sub paint {
    my ($tokn, $Arg, $Api, $core) = @_;
    $core->next_token;
    $tokn->{PAINT} ||=
        Text::Wigwam::Engine::Totem::Paint::Token->new(
            $tokn->{DRAW}[0],
            $core->curr_addr,
            'directive',
        )
    ;

#    if (
#         ($Arg->want & TERM)
#      && !($Arg->type & (TEXT_BLOCK | CODE_BLOCK))
#      && $Arg->mate eq $tokn->{MATE}
#    ){
    if( ($Arg->want & TERM) && !$Arg->type ){
        return(
            Text::Wigwam::Engine::Totem::Paint::Group->new(
                [ $tokn->{PAINT} ]
            ),
            1,
        );# if $Arg->mate eq $tokn->{MATE};
    }
     # If we make it this far, we've got a bogus terminator...

    if( $Arg->want & TERM ){
     # If we're pulling a list, just return the bogus token
        $Api->add_comment( "Unexpected terminator" );
        return(
          Text::Wigwam::Engine::Totem::Paint::Token->new(
              @{$tokn->{DRAW}},
              $core->curr_addr,
            'error'
          ),
          0,
        );
    }

     # If we're not pulling a list, we need to process the next
     # token instead, and piggy-back it to the bogus token.
    my ($text, $end) = $core->curr_token->paint(
        $Arg,
        $Api,
        $core
    );
    $Api->add_comment( "Unexpected terminator" );
    return(
        Text::Wigwam::Engine::Totem::Paint::Group->new(
          [
            Text::Wigwam::Engine::Totem::Paint::Token->new(
                @{$tokn->{DRAW}},
                $core->curr_addr,
            'error',
            ),
            @$text
          ]
        ),
        $end,
    );
}

1;
