
package Text::Wigwam::Engine::Fusion::Template;

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

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

    use Text::Wigwam::Const( qw/TERM EXPR ANY BLOCK STRING VOID/ );

    use constant SIZE => 0;

sub new {
    my ($class, $Api) = @_;
    my $template = bless  [
        $Api->{core}->token_count,  # Template size (token count)
        [],                         # Init EXPR stack
    ], ref($class) || $class;
    return $template->_set_init($Api);
}

sub _get_init { shift @{$_[0]->[1]} }
sub _set_init {
    my ($self, $Api) = @_;
    local $_;
    push(
        @{$self->[1]} =>
        Text::Wigwam::Engine::Fusion::Expression->new(
            $_,                # Addr
            STRING|VOID|BLOCK, # Want
            1,                 # Size (unknown)
            $Api,              # Engine
        )
    ) for $Api->{core}->get_init_addr;
    return $self;
}

sub size { $_[0]->[SIZE] }
sub engine { q/Fusion/ }
sub beautify {
    my ($self, $Api, @args) = @_;
    $self->_rexpr($Api)->beautify( @args );
}

sub prime {
    my ($self, $Api, $Args) = @_;
    $Api->inc_scope( q/TEMPLATE/ );
    my $data = $self->_prime($Api, $Args);
    $Api->dec_scope( q/TEMPLATE/ );
    return $data;
}

sub _prime {
    no warnings 'uninitialized';
    my ($self, $Api, $Args) = @_;
    my ($init, $data);
    $data .= $init->execute($Args)
      while $init = $self->_get_init;
    return $data;
}

sub execute {
    my ($self, $Api, $Args) = @_;
    no warnings 'uninitialized';
    $Api->inc_scope( q/TEMPLATE/ );

    my $data = join( "" =>
        $self->_prime($Api, $Args),          # Process init code
        scalar $self->_rexpr($Api)->execute($Args), # Process the template
    );

    (my $err, $data) = $self->_do_globals( $Api, $data );
    $Api->dec_scope( q/TEMPLATE/ );
    return ( $err, $data ) if wantarray;
    return $data;
}

sub _do_globals {
    my ($self, $Api, $data) = @_;
    if( my ($efnam, $efval, $efscp, $subst, $fatal) = $Api->eflag_info ){
        if( $subst ) {
            warn "Did you mean to use the $efscp scoped global '$efnam' to exit template ".$Api->doc
              unless $efscp eq 'TEMPLATE';
            return ( undef, $$efval );
        }
        elsif ( $fatal ) {
            $efval = $$efval if ref($efval);
            return ($efval, $data);
        }
    }
    return (undef, $data);
}

sub _rexpr {
    my ($self, $Api) = @_;
    return Text::Wigwam::Engine::Fusion::Expression->new(
        $Api->{core}->token_zero,
        ANY | BLOCK,
        $self->[SIZE],
        $Api,
    );
}

1;
