
package Text::Wigwam::Library::Utility::Locals;

    use strict;
    use warnings;
    use Scalar::Util( qw/refaddr/ );
    our $VERSION = '0.01';

sub new {
    my ($class, $Api) = @_;
    return bless {
        localvars => {
            # varname => object
        },
        varspace => undef,
#        Api => $Api,
    }, ref($class) || $class;
}

sub restore {
    my ($self, $Api) = @_;

    # Don't restore anything unless we're restoring to the same varspace that
    # was localized. This prevents the inadvertent clobbering of variables
    # in a parent template when #call'ing child templates with a private
    # varspace.

    if(
         $self->{varspace}
      && $self->{varspace} eq refaddr( $Api->get_value(q/[]/) )
    ){
        $_->restore($Api)
            for (values %{$self->{localvars}});
    }

    %{$self->{localvars}} = ();
    return;
}

sub localize {
    my ($self, $Api, @vars) = @_;
    $self->{varspace} ||= refaddr(scalar $Api->get_value(q/[]/));
    my $localvars = $self->{localvars};
    for my $varname (@vars){
        next if exists $localvars->{$varname};
        $Api->debug(
            "Erroneous results may occur via the localization of globals."
         ) if $Api->is_global($varname);
        $localvars->{$varname}
         = $Api->is_defined($varname)
           ? Text::Wigwam::Library::Utility::Locals::Restore->new(
                $varname,
                $Api->get_value($varname),
             )
           : Text::Wigwam::Library::Utility::Locals::Delete->new($varname)
        ;
        $Api->undefine($varname);
    }
    return;
}

package Text::Wigwam::Library::Utility::Locals::Delete;

    use strict;
    use warnings;

    sub new {
        my ($class, $name) = @_;
        return bless \$name, $class;
    }
    sub restore { $_[1]->undefine( ${$_[0]} ) }

package Text::Wigwam::Library::Utility::Locals::Restore;

    use strict;
    use warnings;

    sub new {
        my ($class, $name, $value) = @_;
        return bless [ $name, $value ], $class;
    }

    sub restore { $_[1]->set_alias( @{$_[0]} ) }

1;
