#!/usr/bin/perl

BEGIN {unshift(@INC, '../../..')}
use strict;
use W3C::Util::Exception qw(&throw &watch &DieHandler);
use W3C::XML::XmlSerializer;

my ($SER, $URI) = (1, 2);
my ($INPUT, $OUTPUT) = (0, 1);
my ($ONE, $TWO, $THREE) = (0, 1, 2);
local($SIG{"__DIE__"}) = sub {&DieHandler(@_)};

print "without namespaces ".	(&watch(\&withoutNamespaces)	? 'ok' : 'failed').".\n";
print "with namespaces ".	(&watch(\&withNamespaces)	? 'ok' : 'failed').".\n";
print "declare namespaces ".	(&watch(\&withNamespaceDecls)	? 'ok' : 'failed').".\n";
print "mixed namespaces ".	(&watch(\&mixedNamespaceDecls)	? 'ok' : 'failed').".\n";
print "search for namespaces ".	(&watch(\&withNamespaceSearcher)? 'ok' : 'failed').".\n";
print "invent new namespasces ".(&watch(\&inventNamespaces)	? 'ok' : 'failed').".\n";

sub withoutNamespaces {
    &simpleTest($SER, 
		[['', ''], 
		 ['', ''], 
		 ['', '']], 
		[[], 
		 [], 
		 []], 1);
    1;
}

sub withNamespaces {
    my $NS = 'http://example.com/ns1#';
    my $PRE = 'ex';
    my $nsh = new W3C::Util::NamespaceHandler();
    $nsh->addNamespace($PRE, $NS);
    &simpleTest($SER, 
		[["${PRE}:", "${PRE}:"],
		 ["${PRE}:", "${PRE}:"], 
		 ["${PRE}:", "${PRE}:"]], 
		[[], 
		 [], 
		 []], 1, -namespaceHandler => $nsh);
    1;
}

sub withNamespaceDecls {
    my $NS = 'http://example.com/ns1#';
    my $PRE = 'ex';
    my $nsh = new W3C::Util::NamespaceHandler();
    $nsh->addNamespace($PRE, $NS);
    &simpleTest($SER, 
		[["${PRE}:", "${PRE}:"], 
		 ["${PRE}:", "${PRE}:"], 
		 ["${PRE}:", "${PRE}:"]], 
		[[[$PRE, $NS]], 
		 [], 
		 []], 1, -namespaceHandler => $nsh);
    1;
}

sub mixedNamespaceDecls {
    my $NS1 = 'http://example.com/ns1#';
    my $PRE1 = 'ex1';
    my $NS2 = 'http://example.com/ns2#';
    my $PRE2 = 'ex2';
    my $nsh = new W3C::Util::NamespaceHandler();
    $nsh->addNamespace($PRE1, $NS1);
    $nsh->addNamespace($PRE2, $NS2);
    &simpleTest($SER, 
		[["${PRE1}:", "${PRE1}:"], 
		 ["${PRE2}:", "${PRE2}:"], 
		 ["${PRE1}:", "${PRE1}:"]], 
		[[[$PRE1, $NS1]], 
		 [[$PRE2, $NS2]], 
		 []], 1, -namespaceHandler => $nsh);
    1;
}

# Preload a namespace handler with a set of namespaces.
# Give the UriXmlSerializer uris from that namespace and have it resolve them.
sub withNamespaceSearcher {
    my $NS = 'http://example.com/ns1#';
    my $PRE = 'ex';
    my $nsh = new W3C::Util::NamespaceHandler();
    $nsh->addNamespace($PRE, $NS);
    &simpleTest($URI, 
		[["${NS}", "${PRE}:"], 
		 ["${NS}", "${PRE}:"], 
		 ["${NS}", "${PRE}:"]], 
		[[[$PRE, $NS]], 
		 [], 
		 []], 1, -namespaceHandler => $nsh);
    1;
}

# Give the UriXmlSerializer uris from a namespace. It asks the namespace
# inventor for prefixes. The return value from this call tells the XmlSerializer
# to make declarations for the new namespaces.
sub inventNamespaces {
    my $NS1 = 'http://example.com/ns1#';
    my $PRE1 = 'ns1';
    my $NS2 = 'http://example.com/ns2#';
    my $PRE2 = 'ns2';
    my $NS3 = 'http://example.com/ns3#';
    my $PRE3 = 'ns3';
    my $nsh = new W3C::Util::NamespaceInventor();
    &simpleTest($URI, 
		[["${NS1}", "${PRE1}:"], 
		 ["${NS2}", "${PRE2}:"], 
		 ["${NS3}", "${PRE3}:"]], 
		[[[$PRE1, $NS1]], 
		 [[$PRE2, $NS2], [$PRE3, $NS3]], 
		 []], 0, -namespaceHandler => $nsh);
    1;
}

sub simpleTest {
    my ($class, $prefixes, $extras, $doDecls, %flags) = @_;
    my $s = $class == $SER ? 
	new W3C::XML::XmlSerializer(-prettyPrint => 1, %flags) :
	new W3C::XML::UriXmlSerializer(-prettyPrint => 1, %flags);
    $s->addXmlDecl();
    if ($doDecls) {
	foreach my $extra (@{$extras->[$ONE]}) {
	    $s->pendNamespace(@$extra);
	}
    }
    # &{$extras->[0]}($s) if ($extras->[0]);
    $s->startElement("$prefixes->[$ONE][$INPUT]one", {});
    if ($doDecls) {
	foreach my $extra (@{$extras->[$TWO]}) {
	    $s->pendNamespace(@$extra);
	}
    }
    $s->startElement("$prefixes->[$TWO][$INPUT]two", {"$prefixes->[$THREE][$INPUT]three" => "four"});
    $s->characters("charaters");
    $s->endElement("$prefixes->[$TWO][$INPUT]two");
    $s->endElement("$prefixes->[$ONE][$INPUT]one");
    $s->flush();
    my $r = $s->getText();
    my $nsDecls1 = join('', map {"\n xmlns:$_->[0]=\"$_->[1]\""} @{$extras->[$ONE]});
    my $nsDecls2 = join('', map {"\n    xmlns:$_->[0]=\"$_->[1]\""} @{$extras->[$TWO]});
    my $e = <<EOF
<?xml version="1.0"?>
<$prefixes->[$ONE][$OUTPUT]one$nsDecls1>
   <$prefixes->[$TWO][$OUTPUT]two$nsDecls2
    $prefixes->[$THREE][$OUTPUT]three="four">charaters</$prefixes->[$TWO][$OUTPUT]two>
</$prefixes->[$ONE][$OUTPUT]one>
EOF
    ;
    if ($r ne $e) {
	my $msg = "expected:\n$e\ngot:\n$r";
	&throw(new W3C::Util::Exception(-message => $msg));
    }
    print $e if ($ARGV[0] eq '-v');
}

