
package Text::Wigwam::Engine::Fusion::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::Fusion::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::Fusion::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::Fusion::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::Fusion::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::Fusion::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::Fusion::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::Fusion::Paint::Group->new(
              [
                Text::Wigwam::Engine::Fusion::Paint::Token->new(
                    @{$tokn->{DRAW}},
                    $core->curr_addr,
                'error'
                ),
                @$text
              ]
            ),
            $end,
        );
    }

1;
