use 5.006;
use strict;
use warnings;

=head1 NAME

EJS::Template::Executor - Executes JavaScript generated by EJS::Template

=cut

package EJS::Template::Executor;
use base qw(EJS::Template::Base EJS::Template::IO);

use EJS::Template::JSAdapter;
use EJS::Template::Runtime;

=head1 Methods

=head2 execute

Executes JavaScript code.

    $executor->execute($input, $variables, $output);

The C<$input> is used as the JavaScript source code, C<$variables> is a hash
ref of variables for JavaScript, and C<$output> is the output destination

=cut

sub execute {
    my ($self, $input, $variables, $output) = @_;
    
    my $js;

    $self->input($input, sub {
        my ($in) = @_;
        local $/;
        $js = <$in>;
    });

    my $ret;

    $self->output($output, sub {
        my ($out) = @_;

        my $runtime = EJS::Template::Runtime->new($self);
        my $adapter = $self->adapter;
        $adapter->bind({print => sub { print $out @_ }});
        $adapter->bind({EJS => $runtime->make_map()});
        $adapter->bind($variables);

        if (defined($js)) {
            $ret = $adapter->eval($js);
            die $@ if $@;
        } else {
            $ret = 1;
        }
    });
    
    return $ret;
}

=head2 adapter

Usage:

    # Getter
    $executor->adapter;

    # Setter
    $executor->adapter(EJS::Template::JSAdapter->create('JE'));

Gets or sets an C<EJS::Template::JSAdapter> object.

=cut

sub adapter {
    my $self = shift;

    if (@_) {
        my $old = $self->{adapter};
        $self->{adapter} = shift;
        return $old;
    } else {
        return $self->{adapter} ||= EJS::Template::JSAdapter->create($self->{config}{engine});
    }
}


=head1 SEE ALSO

=over 4

=item * L<EJS::Template>

=back

=cut

1;
