package Wiki::Toolkit::Store;
use base Wiki::Toolkit::Base;
our $VERSION = '0.00_01';
use strict; use warnings; use Carp;

=head1 METHODS

=over 4

=item B<store manipulation>

  new

=item B<node manipulation>

  get_node, new_node, open_node, save_node, delete_node*

=item B<node storage>

  read_metadata*, write_metadata*, read_content*, write_content*

=item B<node information/listings>

  node_exists*, latest_version*, list_nodes

=item B<other>

  default_node_class, valid_name

=item B<private>

  _filter_list, _list_all_nodes*, _list_all_nodes_all_versions*, _set_latest*

=back

=cut

use Scalar::Util qw( blessed );

sub new_node {
  my $self = shift;
  # FIXME: Change Wiki::Toolkit::Node to $default_nodeclass or somesuch.
  return $self->default_node_class()->new( source => $self, @_ );
}

sub open_node {
  my $self = shift;

  my $name = shift;
  my $version;
  if (blessed $name && $name->isa('Wiki::Toolkit::Node')) {
    $version = $name->metadata('version');
    $name = $name->metadata('name');
  } else {
    $version = shift;
  }

  return undef unless $self->node_exists($name,$version);

  my $meta = $self->read_metadata($name,$version);
  return $self->default_node_class()->new( metadata => $meta, 
                                           source => $self );
}
  
sub get_node {
  my $self = shift;
  my $node = shift;
  my $version = shift;
  return $self->node_exists($node,$version)
    ? $self->open_node($node,$version)
    : $self->new_node($node,@_);
}
  
sub save_node {
  my $self = shift;
  my $node = shift;

  $self->write_metadata($node);
  $self->write_content($node);
  $self->_set_latest($node->name,$node->version) if $node->is_latest();
  return $node;
}


sub list_nodes {
  my ($self, %args) = @_;
  my @list = $self->_list_all_nodes();
  @list = $self->_filter_list( \@list, $args{metadata} || $args{filters} )
    if ($args{metadata} || $args{filters});
  # FIXME: implement sorting
  return wantarray ? @list : \@list;
}
  
sub default_node_class {
  my $self = shift;
  my $node_class = $self->registry->get($self->name,'default_node_class') 
    || 'Wiki::Toolkit::Node';
  eval "require $node_class";
  croak "Could not load $node_class" if ($@);
  return $node_class;
}

sub valid_name {
  my ($self,$name,$version) = @_;
  return ($version =~ /^\d+$/ || $version eq 'latest') && $name;
}

sub _filter_list {
  my ($self, $list, $filters) = @_;
  my ($key, $search, @tmp);
  my @list = @$list;
  my @filters = @$filters;

  while (@filters) {
    $key = shift @filters;
    $search = shift @filters;
    @list = grep { $_->grep_metadata($key,$search) } @list;
  }
  return wantarray ? @list : \@list;
}
