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

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

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

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

sub new { return bless { DRAW => $_[1], TYPE => 'tagentity' } }
sub type { $_[0]->{TYPE} }
sub exec {
    my ($tokn, $want, $Arg, $Api, $core) = @_;
    if( $Arg->type == CODE_BLOCK ){
         # All's well, optimize
        bless $tokn, 'Text::Wigwam::Engine::Totem::Token::Terminator::Fast'
          if $Api->get_options( qw/strict_tags/ );
        $core->next_token;
        $Arg->end_list(1);
        return;
    }

    # No other "typed" terminators should ever be encountered here.
#    if( $Arg->type ) {
#        $Api->exception(
#            "Encountered a code terminator while expecting '"
#          . $Arg->mate
#          . "'. "
#          . "This should never happen, so the problem may lie "
#          . "in the parsing engine"
#          . $Arg->mate
#        );
#        $core->next_token;
#        $Arg->end_list(1);
#        return;
#    }
    if( $Api->get_options( qw/strict_tags/ ) ){
        if( $Arg->type == (ROOT_BLOCK|CODE_BLOCK) ) {
            $Api->exception(
                "Encountered a misplaced code terminator"
            );
            $core->next_token;
            return;
        }
        elsif( $want & TERM ){
            $Api->exception(
                "Encountered an unexpected code terminator while "
              . "expecting ".$Arg->mate
            );
#            $core->next_token;
            $Arg->end_list(1);
            return;
        }
         # Must be a non-list argument
        $Api->exception(
            "Missing argument: An unexpected tag terminator "
          . "was encountered while executing an argument for "
          . $Arg->drip->token."."
        );
#        $core->next_token;
        return $tokn->cast( $Arg, $Api, $want, STRING );
    }

    if( $want & TERM ){
        $Arg->end_list(1);
        return;
    }
    $Api->debug(
        "Missing argument: An unexpected tag terminator "
      . "was encountered while executing an argument for "
      . $Arg->drip->token."."
    );
    return $tokn->cast( $Arg, $Api, $want, STRING );
}
sub skip {
    my ($tokn, $list, $Arg, $Api, $core) = @_;
     # Passive block optimization requires the we just continue
     # along when skipping a text block.
    if( $Arg->type & TEXT_BLOCK ) {
        $core->next_token;
        return;
    }
    if( $Arg->type == CODE_BLOCK ){
        $core->next_token;
         # All's well, optimize
        bless $tokn, 'Text::Wigwam::Engine::Totem::Token::Terminator::Fast'
          if $Api->get_options( qw/strict_tags/ );
        return TERM;
    }
    else {
       if( $list ){
        $Api->exception(
           "Missing terminator token? An unexpected code block terminator "
         . "was encountered while pulling an argument for a list "
         . "directive (" . $Arg->drip->token . ")."
        ) if !( $Arg->type & CODE_BLOCK ) && $Api->get_options( qw/strict_tags/ );
        return TERM;
       }
        # Strict template code enforcement feature
       $Api->exception(
           "Missing argument: An unexpected code block terminator "
         . "was encountered while pulling an argument for "
         . $Arg->drip->token
       ) if $Api->get_options( qw/strict_tags/ );
       return;
    }
    return $core->next_token->skip( $list, $Arg, $Api, $core );
#    $core->next_token;    # Ignore implied terminator
#    return $core->curr_token->skip( $list, $Arg, $Api, $core );
}
sub paint {
    my ($tokn, $Arg, $Api, $core) = @_;
    $tokn->{PAINT} ||= [
        Text::Wigwam::Engine::Totem::Paint::Token->new(
            $tokn->{DRAW}[0],
            $core->curr_addr,
            $tokn->type,
        )
    ];
    if( $Arg->type == CODE_BLOCK ){ # All is well
        $core->next_token;
        return(
          Text::Wigwam::Engine::Totem::Paint::Group->new(
            [ @{$tokn->{PAINT}} ]
          ),
          1,
        );
    }

    # If we make it this far, we've got a misplaced tag terminator

    if( $Arg->want & TERM ){
      if( $Arg->type ){
        $core->next_token;
        $Api->add_comment( "Encountered a misplaced code block terminator" );
        return(
          Text::Wigwam::Engine::Totem::Paint::Group->new(
            [ @{$tokn->{PAINT}} ]
          ),
          0, # Don't terminate the list
        );
      }
      return(
        Text::Wigwam::Engine::Totem::Paint::Group->new(
         [
          Text::Wigwam::Engine::Totem::Paint::Token->new(
            $Arg->mate || (
                ($Arg->type & CODE_BLOCK) ? $Api->get_options('code_term')
              : ($Arg->type & ROOT_BLOCK) ? $Arg->mate
              : '#/*'
            ),
            $core->curr_addr,
            'implied',
          )
         ]
        ),
        1,
      );
    }

    $Api->add_comment( "Directive is missing an argument" );
    return(
      Text::Wigwam::Engine::Totem::Paint::Group->new(
        [
            Text::Wigwam::Engine::Totem::Paint::Token->new(
                '('.$tokn->show_needs($Arg->want).')',
                $core->curr_addr,
                'error'
            )
        ]
      ),
      1
    ); # Missing argument
}

1;
