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

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

class WWW::DataWiki::Resource::Version
	extends WWW::DataWiki::Resource
	with WWW::DataWiki::Trait::RdfModel
	with WWW::DataWiki::Trait::LastModified
	with WWW::DataWiki::Trait::Title
	with WWW::DataWiki::Trait::Negotiator
{
	use File::Spec;
	use RDF::TriN3;
	use PerlIO::gzip;
	use RDF::Trine qw[statement iri literal blank];
	use RDF::QueryX::Lazy;
	use WWW::DataWiki::Utils;
	
	has page    => (is => 'ro', isa => 'WWW::DataWiki::Resource::Page', required=>1);
	has version => (is => 'ro', isa => 'Str', required=>1);

	my $version_parser = DateTime::Format::Strptime->new(pattern=>'%Y%m%dT%H%M%SZ');

	method storage
	{
		return File::Spec->catfile($self->page->storage, sprintf('%s.n3.gz', $self->version));
	}

	method title_string
	{
		return sprintf('%s (%s)', $self->page->wikiname, $self->last_modified);
	}

	method last_modified
	{
		return $version_parser->parse_datetime($self->version);
	}

	method page_iri
	{
		return $self->page->page_iri($self->version);
	}

	method version_iri
	{
		return $self->page->version_iri($self->version);
	}

	method formatted_page_iri ($format)
	{
		return $self->page->formatted_page_iri($format);
	}

	method formatted_version_iri ($format)
	{
		return $self->page->formatted_version_iri($self->version, $format);
	}

	method rdf_model
	{
		my $model  = RDF::Trine::Model->new;
		my $parser = RDF::Trine::Parser::Notation3->new;
		$WWW::DataWiki::Trait::RdfModel::MAP = $parser->{bindings};
		$parser->parse_into_model($self->page_iri->uri, $self->rdf_string, $model);
		return $model;
	}

	method rdf_string
	{
		open my $fh, "<:gzip", $self->storage;
		return do { local $/ = <$fh> };
	}

	method rdf_gzipped
	{
		open my $fh, '<', $self->storage;
		return do { local $/ = <$fh> };
	}
	
	method accepts_updates
	{
		1.1;
	}
	
	method execute_update ($sparql)
	{
		my $model = $self->rdf_model;
		my $query = RDF::QueryX::Lazy->new($sparql, {update=>1})
			or die RDF::QueryX::Lazy->error;
		$query->execute($model);
		
		return $self->page->create_version($model);		
	}

	method create_version_from_append_string (Str $string, Str $format)
	{
		$format = WWW::DataWiki::Utils->canonicalise_rdf_format($format);
		return unless $format;
		
		my $model = WWW::DataWiki::Utils->parse($string, $format, $self->page_iri->uri);
		return unless $model;

		my $appended = $self->rdf_string;
		$appended .= sprintf("\n\@base <%s> .\n\n", $self->page_iri->uri);
		
		if ($format eq WWW::DataWiki->FMT_N3
		or  $format eq WWW::DataWiki->FMT_TTL
		or  $format eq WWW::DataWiki->FMT_NT)
		{
			$appended .= "$string\n";
		}
		else
		{
			my $ser = RDF::Trine::Serializer->new('Turtle'); # it's not N3, so Turtle is safe
			$appended .= $ser->serialize_model_to_string($model);
		}
		
		return $self->page->create_version($appended);
	}
	
	method store_meta ($data)
	{
		return $self->page->store_meta($data, $self->version);
	}
}

1;
