package Text::Wigwam::Virtual;

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

sub AUTOLOAD {
    my ($self, @args) = @_;
#    return if our $AUTOLOAD =~ /::DESTROY$/;
    my ($meth) = our $AUTOLOAD =~ /.*::(.*)$/;
    warn "Executing $meth method as invoked by ".join( ", " => caller);
    my (undef, $file, $line) = caller();
    my $exports = $self->_exports || {};
    if( ref($self) ) {
        if (
            $self->_template->explicit_is_defined(
                $exports,
                ".",
                $meth,
            )
        ) {
            my $data = $self->_retrieve_export($meth);
            if( (my $Api = $self->_api)->is_expr($data) ){
                my ($err, $val) = $data->execute( [ $self, @args ] );
                if( $err ) {
                    $Api->reset_eflags;
                    die $err;
                }
                return $self->_return($val);
            }
            return $self->_return($data);
        }
    # My inheritence code could probably use some closer scrutiny.
        no strict 'refs';
        my @iza = @ISA;
        my %done;
        while( my $fallback = shift @iza) {
            next if $done{$fallback}++;
            unshift(@iza, @{"$fallback\::ISA"} );
            if( $fallback->can($meth) || $fallback->can('AUTOLOAD') ){
                my $pkg = join( '::' => $fallback, $meth );
                return $pkg->($self, @args);
            }
        }
    }
    die "Virtual method '$meth' is not exported by "
        . ($self->_template->doc)
        . ". in $file, line $line."
        . "Valid methods are: "
        . join( ", " => keys %$exports )
    ;
}

sub DESTROY { }

sub _return {
    my ($self, $result) = @_;
    my $Api = $self->_api;
    return $Api->is_list($result)
           ? @$result
           : $Api->is_hash($result)
             ? %$result
             : $result
    ;
}

sub new {
    my ($class, $twobj) = @_;
    my %self = (
        Template => $twobj,
    );
    return bless \%self, $class;
}

sub _exports {
    my ($self) = @_;
    return $self->_template->_export;
}

sub _retrieve_export {
    my ($self, $meth) = @_;
    my $exports = $self->_exports;
    return $self->_template->explicit_get_value(
        $exports,
        ".",
        $meth,
    );
}
sub _api { $_[0]->_template->{engine} }
sub _template { $_[0]->{Template}->prime }

1;

__END__

This class wraps around a Text::Wigwam template object and enables templates
to simulate Perl objects where method calls are mapped to exported values
and/or macros.

