The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use 5.010;
use strict;
use MooseX::Declare;

BEGIN
{
	$WWW::DataWiki::Controller::Container::AUTHORITY = 'cpan:TOBYINK';
	$WWW::DataWiki::Controller::Container::VERSION   = '0.001';
}

class WWW::DataWiki::Controller::Container
	extends WWW::DataWiki::Controller
{
	use CatalystX::Syntax::Action;
	use Data::UUID qw(NameSpace_URL);
	use File::Slurp qw(slurp);
	use URI::Escape qw(uri_escape);
	
	has uuid_generator => (is => 'ro', isa => 'Data::UUID', lazy => 1, builder => '_build_uuid_generator');
	
	our $RE_page = '((?:[a-z][a-z0-9-]*[a-z0-9])(?:/[a-z][a-z0-9-]*[a-z0-9])*)';
	our $RE_path = "${RE_page}/";
	
	__PACKAGE__->config(
		namespace => '',
		action => {
			container   => { Regex => "^${RE_path}\$" },
			end         => { Private => 1 },
			},
		);
		
	method _build_uuid_generator
	{
		return Data::UUID->new;
	}

	action container { $self->_dispatch_by_method($ctx, 'container'); }

	action container_GET
	{
		my ($wikiname) = @{ $ctx->req->captures || [] };
		$wikiname //= '';
		
		my $c = $ctx->model('Wiki')->container("${wikiname}/");
		WWW::DataWiki::Exception->throw(404 => 'Container not found') unless defined $c;
		#WWW::DataWiki::Exception->throw(404 => 'Container not found') unless $c->all_member_names; # somewhat of a hack
		$ctx->stash(resource => $c);

		if (WWW::DataWiki::Controller::Query->req_is_query($ctx->req))
		{
			$ctx->detach('Controller::Query', 'query');
		}		
	}

	action container_POST 
	{
		my ($wikiname) = @{ $ctx->req->captures || [''] };
		
		my $c = $ctx->model('Wiki')->container("${wikiname}/");
		WWW::DataWiki::Exception->throw(404 => 'Container not found') unless defined $c;
		#WWW::DataWiki::Exception->throw(404 => 'Container not found') unless $c->all_member_names; # somewhat of a hack
		$ctx->stash(resource => $c);
		
		if (WWW::DataWiki::Controller::Query->req_is_query($ctx->req))
		{
			$ctx->detach('Controller::Query', 'query');
		}
		elsif (defined (my $fmt = WWW::DataWiki::Utils->canonicalise_rdf_format($ctx->req->content_type)))
		{
			my $slug = lc $ctx->req->header('Slug');
			$slug =~ s/[^a-z0-9]/-/;
			$slug =~ s/[-]{2,}/-/g;
			(my $full = "${wikiname}/${slug}") =~ s{^/}{};
			while ( $ctx->model('Wiki')->page($full)->latest_version )
			{
				$slug++;
				($full = "${wikiname}/${slug}") =~ s{^/}{};
			}
			$slug = sprintf('uuid-%s', lc $self->uuid_generator->create_from_name_str(NameSpace_URL, $c->container_iri->uri))
				unless $slug =~ /^[a-z][a-z0-9-]*[a-z0-9]$/;

			($full = "${wikiname}/${slug}") =~ s{^/}{};
			my $page = $ctx->model('Wiki')->page($full);
			my $data = $ctx->req->body;
			$data = slurp($data)
				if $data =~ m#^/# && -f $data;
				
			my $new = $page->create_version_from_string($data, $fmt);
			if ($new)
			{
				$new->store_meta( WWW::DataWiki::Utils->ctx_to_provenance($ctx) );
				
				$ctx->set_http_status_code(201 => 'Created');
				$ctx->stash(resource => $new);
			}
			else
			{
				WWW::DataWiki::Exception->throw(500 => 'Error creating page');
			}						
		}
		else
		{
			WWW::DataWiki::Exception->throw(415 => 'Unsupported media type',
				'This resource accepts POST requests using SPARQL Query, and accepts RDF data to create a new resource in the collection.',
				{'X-Accept' => 'application/x-www-form-urlencoded, application/sparql-query, text/n3, text/turtle, text/plain, application/rdf+xml;q=0.5, application/json;q=0.1, application/xhtml+xml;q=0.1, text/html;q=0.1'});
		}
	}

	action container_OPTIONS
	{
		my ($wikiname) = @{ $ctx->req->captures || [] };
		$wikiname //= '';
		
		my $c = $ctx->model('Wiki')->container("${wikiname}/");
		WWW::DataWiki::Exception->throw(404 => 'Container not found') unless defined $c;
		$ctx->stash(resource => $c->help);
	}

	action container_HEAD { goto &container_GET; }

	action container_BREW
	{
		$self->HTCPCP($ctx);
	}
	
	*container_WHEN    =
		\&container_BREW;
}

1;