package Template::Plugin::StringTree::Node;

# This package implements the actual nodes in the StringTree.
# We need to be very careful not to pollute this namespace with methods.

use 5.005;
use strict;
use Scalar::Util ();
use overload '""'   => '__get';

use vars qw{$VERSION %STRING};
BEGIN {
	$VERSION = '0.08';

	# Data store for the Nodes
	%STRING  = ();
}

# Create a new node, with an optional value
sub __new {
	my $class = ref $_[0] ? ref shift : shift;
	my $self  = bless {}, $class;

	if ( defined $_[0] and ! ref $_[0] ) {
		# The value for this node
		$STRING{Scalar::Util::refaddr($self)} = shift;
	}

	$self;
}

# Get the value for this node
sub __get {
	my $self = ref $_[0] ? shift : return undef;
	$STRING{Scalar::Util::refaddr($self)};
}

# Set the value for this node
sub __set {
	my $self = ref $_[0] ? shift : return undef;
	if ( defined $_[0] ) {
		$STRING{Scalar::Util::refaddr($self)} = shift;
	} else {
		delete $STRING{Scalar::Util::refaddr($_[0])};
	}

	1;
}

# Methods compatible with UNIVERSAL will die in a major way.
# Fortunately, we can tell if 'isa' and 'can' calls are meant to be genuine
# or not. The two-argument form is passed though, the one-argument form
# is treated by descending.
sub isa {
	my $self = shift;
	return $self->SUPER::isa(@_) if @_;
	exists $self->{isa} ? $self->{isa} : undef;
}
sub can {
	my $self = shift;
	return $self->SUPER::can(@_) if @_;
	exists $self->{can} ? $self->{can} : undef;
}

# Unfortunately, we have no choice but to use this name.
# To prevent pollution, we'll throw an error should we ever try to set
# a value using a DESTROY segment in a path.
sub DESTROY {
	delete $STRING{Scalar::Util::refaddr($_[0])} if ref $_[0];
}

1;