use 5.010;
use utf8;
use MooseX::Declare;

BEGIN
{
	$WWW::DataWiki::Model::Wiki::AUTHORITY = 'cpan:TOBYINK';
	$WWW::DataWiki::Model::Wiki::VERSION   = '0.000_01';
}

class WWW::DataWiki::Model::Wiki
	extends Catalyst::Model
	is mutable
{
	use DateTimeX::Format::Ago;
	use HTML::HTML5::Builder qw[:standard link];
	use XML::LibXML::PrettyPrint;
	
	has 'context' => (is => 'rw', isa => 'Catalyst');
	
	method ACCEPT_CONTEXT ($ctx)
	{
		$self->context($ctx);
		return $self;
	}
	
	method container ($wikiname)
	{
		return WWW::DataWiki->resource_class('Container')->new(
			wikiname => $wikiname,
			context  => $self->context,
			);
	}
	
	method page ($wikiname)
	{
		return WWW::DataWiki->resource_class('Page')->new(
			wikiname => $wikiname,
			context  => $self->context,
			);
	}
	
	method version ($wikiname, $version_string?)
	{
		my $page = $self->page($wikiname);
		return $page->latest_version unless defined $version_string;
		return $page->latest_version_as_of($version_string);
	}

	method editor ($wikiname)
	{
		my $page = WWW::DataWiki->resource_class('Page')->new(
			wikiname => $wikiname,
			context  => $self->context,
			);
		
		my $dom  = html(
			-lang => 'en', '-xml:lang' => 'en', -version => 'XHTML+RDFa 1.1',
			head(
				title('Edit: ', $page->title_string),
				HTML::HTML5::Builder::link(-rel=>'stylesheet', -type=>'text/css', -href=>'/static/styles/editor.css', -media=>'screen,projection'),
				),
			body(
				h1('Edit: ', $page->title_string),
				form(-action=>'', -method => 'post',
					div(
						textarea(-name => 'body', -id => 'body', -rows => 15, -cols => 60, $page->latest_version->rdf_string_as(WWW::DataWiki->FMT_N3, 0)),
						br(),
						input(-type=>'submit', -value=>'Submit as new version'),
						' using ', label(-for=>'content-type', 'syntax'), ' ',
						HTML::HTML5::Builder::select(
							-name => 'content-type',
							-id   => 'content-type',
							map { option($_) } qw[text/n3 text/turtle text/plain]
							),
						),
					),
				WWW::DataWiki::Model::Wiki->standard_footer,
				),
			);
			
		return WWW::DataWiki->resource_class('Information')->new(dom => $dom);
	}	

	method standard_footer ($class:)
	{
		div(-class=>'footer', hr(),address(sprintf('Powered by WWW::DataWiki/%s (%s)', WWW::DataWiki->VERSION, WWW::DataWiki->AUTHORITY)));
	}
	
	method help ($wikiname, $version_string?)
	{
		my $page = $self->page($wikiname);
		my $dom  = html(
			-lang => 'en', '-xml:lang' => 'en', -version => 'XHTML+RDFa 1.1',
			-prefix => 'srv: http://ontologi.es/srv# u: http://purl.org/NET/uri# rdfs: http://www.w3.org/2000/01/rdf-schema# ht: http://www.w3.org/2011/http# hth: http://www.w3.org/2011/http-headers# htm: http://www.w3.org/2011/http-methods# htc: http://www.w3.org/2011/http-statusCodes#',
			head(
				title('HTTP Options for ', $page->page_iri),
				HTML::HTML5::Builder::link(-rel=>'stylesheet', -type=>'text/css', -href=>'/static/styles/page.css', -media=>'screen,projection'),
				),
			body(-about=>'[_:This]', -typeof=>'srv:Endpoint',
				h1(-lang=>'en', -rel=>'srv:uri_base', 'HTTP Options for ', span(-property=>'u:identifier', -content=>$page->page_iri->uri, $page->page_iri)),
				ul(-rev=>'srv:endpoint',
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:OPTIONS]', 'OPTIONS'), ' ',
							),
						div(-property=>'rdfs:comment',
							'Shows this help.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:GET]', 'GET'), ' ',
							'with no parameters',
							),
						div(-property=>'rdfs:comment',
							'Retrieves the graph.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:GET]', 'GET'), ' ',
							span(-rel=>'srv:req_param', 'with parameter ', em(-property=>'srv:name', 'query')),
							),
						div(-property=>'rdfs:comment',
							'Queries the graph with SPARQL, returning the results.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:POST]', 'POST'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-property=>'ht:fieldValue', 'application/x-www-form-urlencoded'))), ' ',
							span(-rel=>'srv:req_param', 'with parameter ', em(-property=>'srv:name', 'query')),
							),
						div(-property=>'rdfs:comment',
							'Queries the graph with SPARQL, returning the results.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:POST]', 'POST'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-property=>'ht:fieldValue', 'application/sparql-query'))),
							),
						div(-property=>'rdfs:comment',
							'Queries the graph with SPARQL, returning the results.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:PUT]', 'PUT'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-rel=>'srv:fieldValueRange', -resource=> '[_:RDF]', '(an RDF serialisation)'))),
							),
						div(-property=>'rdfs:comment',
							'Replaces the graph, responding with the new version of the graph.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:POST]', 'POST'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-rel=>'srv:fieldValueRange', -resource=> '[_:RDF]', '(an RDF serialisation)'))),
							),
						div(-property=>'rdfs:comment',
							'Appends to the graph, responding with the new version of the graph.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:POST]', 'POST'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-property=>'ht:fieldValue', 'application/x-www-form-urlencoded'))), ' ',
							span(-rel=>'srv:req_param', 'with parameter ', em(-property=>'srv:name', 'update')),
							),
						div(-property=>'rdfs:comment',
							'Updates the graph with SPARQL Update, responding with the new version of the graph.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:POST]', 'POST'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-property=>'ht:fieldValue', 'application/sparql-update'))),
							),
						div(-property=>'rdfs:comment',
							'Updates the graph with SPARQL Update, responding with the new version of the graph.'
							),
						),
					li(-typeof=>'srv:Action',
						div(
							strong(-rel=>'srv:req_method', -resource=>'[htm:PATCH]', 'PATCH'), ' ',
							span(-rel=>'srv:req_header', 'with header ', em(-typeof=>'ht:RequestHeader', span(-rel=>'ht:hdrName', -resource=>'[hth:content-type]', -property=>'ht:fieldName','Content-Type'), ': ', span(-property=>'ht:fieldValue', 'application/sparql-update'))),
							),
						div(-property=>'rdfs:comment',
							'Updates the graph with SPARQL Update, responding with the new version of the graph.'
							),
						),
					),
				WWW::DataWiki::Model::Wiki->standard_footer,
				),
			);
		
		# We don't really need to pretty-print this, but it's only a small DOM.
		my $pp = XML::LibXML::PrettyPrint->new_for_html;
		push @{$pp->{element}{preserves_whitespace}}, sub
		{
			if ($_[0]->hasAttribute('property') and not $_[0]->hasAttribute('content'))
			{
				# Preserve whitespace when element is an RDFa literal.
				return 1;
			}
			return undef;
		};
		$pp->pretty_print($dom);
		
		return WWW::DataWiki->resource_class('Information')->new(dom => $dom);
	}
}

1;
