package NIML;

use strict;
use warnings;
use Object;
use Lib;
use base 'Object';

sub new {
	my ($class, $self) = @_;
	$self = $class->SUPER::new($self);
	$self->{doc}  //= undef;  # xml document, as text
	$self->{ary}  //= undef;  # split into a list of elements
	$self->{tree} //= undef;  # tree - 'text' or [tag, ...]
	$self->{dat}  //= undef;  # data to bind
	return $self;
}

sub split {
	my ($self) = @_;
	$self->{ary} = [$self->{doc} =~ m{<.*?>\s*|[^<]+}g];
}

sub tag_parse {
	my ($txt) = @_;
	my ($close, $tag, $attr, $single) = $txt =~ m{^<(/)?(\w+)(.*?)(/)?>};
	return if !defined $tag;
	my $open = !$close;
	$close ||= $single;
	return ($open, $close, $tag, $attr);
}

sub make_tree {
	my ($self) = @_;
	my $tree = [];
	my @stack;
	for my $e (@{$self->{ary}}) {
		my ($open, $close, $tag, $attr) = tag_parse($e);
		if ($open) {
			my $e = ["$tag$attr"];
			push @$tree, $e;
			if (!$close) {
				push @stack, $tree;
				$tree = $e;
			}
		} elsif ($close) {
			@stack or die "close tag at top level: $e\n";
			my $up = pop @stack;
			my ($open_tag) = $up->[-1][0] =~ /^(\w+)/;
			$tag eq $open_tag or die "tag mismatch: $open_tag $tag\n";
			$tree = $up;
		} else {
			push @$tree, $e;
		}
	}
	@stack and die "unclosed tag at end: $stack[-1][-1][0]\n";
	$self->{tree} = $tree;
}

sub flatten_tree {
	my ($self) = @_;
	$self->{ary} = [];
	for my $e (@{$self->{tree}}) {
		$self->flatten_tree_2($e);
	}
}

sub flatten_tree_2 {
	my ($self, $e) = @_;
	my $ary = $self->{ary};
	if (ref $e) {
		my $tagattr = $e->[0];
		my ($tag) = $tagattr =~ /^(\w+)/;
		push @$ary, "<$tagattr>";
		for my $i (1..$#$e) {
			$self->flatten_tree_2($e->[$i]);
		}
		push @$ary, "</$tag>";
	} else {
		push @$ary, $e;
	}
}

sub join {
	my ($self) = @_;
	$self->{doc} = joinlines $self->ary;
}

sub bind {
	my ($self) = @_;
	my $tree = $self->{tree};
	my $tree2 = [];
	bind2($tree2, self->{tree}, 0, $#$
	my $doc = NIML->new(tree=>$tree2);
	return $doc;
}



sub test {
	my ($open, $close, $tag, $attr) = tag_parse(q{<a href="foo">});
	$open && !$close && $tag eq "a" && $attr eq qq{ href="foo"}
	  or die "tag_parse failed\n";

	my $tmpl = NIML->new;
	$tmpl->doc(qt qq{
		<html>
		<head><title n="title">Hello World</title></head>
		<body>
		<h1 n="title">Hello World</h1>
		<p n="content"/>
		</body>
		</html>
	});
	$tmpl->split;
	$tmpl->make_tree;
	$tmpl->dat({
		title => "Hello World",
		content => [
			'This is nice',
			'A little bit exciting! to be positive.',
		]
	});
	my $doc = $tmpl->bind;
	$doc->flatten_tree;
	$doc->join;
#	print D $doc->tree;
	print D $doc->ary;
	print $doc->doc;
}

1;
