package Blerg::Database;

use 5.008000;
use strict;
use warnings;
use Carp;

require Exporter;
use AutoLoader;

our @ISA = qw(Exporter);

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration	use Blerg::Database ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
	
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
	
);

our $VERSION = '1.9.0';

sub AUTOLOAD {
    # This AUTOLOAD is used to 'autoload' constants from the constant()
    # XS function.

    my $constname;
    our $AUTOLOAD;
    ($constname = $AUTOLOAD) =~ s/.*:://;
    croak "&Blerg::Database::constant not defined" if $constname eq 'constant';
    my ($error, $val) = constant($constname);
    if ($error) { croak $error; }
    {
	no strict 'refs';
	# Fixed between 5.005_53 and 5.005_61
#XXX	if ($] >= 5.00561) {
#XXX	    *$AUTOLOAD = sub () { $val };
#XXX	}
#XXX	else {
	    *$AUTOLOAD = sub { $val };
#XXX	}
    }
    goto &$AUTOLOAD;
}

require XSLoader;
XSLoader::load('Blerg::Database', $VERSION);

# Preloaded methods go here.

if (!Blerg::Database::init()) {
    die "Could not initialize C library";
}

sub open {
    my ($class, $name) = @_;
    my $ptr = Blerg::Database::_open($name);
    my $obj = {
        ptr => $ptr,
        name => $name,
    };
    return bless $obj, $class;
}

sub open_existing {
    my ($class, $name) = @_;

    if (Blerg::Database::exists($name)) {
        return Blerg::Database->open($name);
    }
    return undef;
}

sub _ensure_pointer {
    my ($obj) = @_;
    if (!defined $obj->{ptr}) {
        croak "Attempted to use closed Blerg::Database";
    }
}

sub close {
    my ($obj) = @_;
    if (!(defined $obj && defined $obj->{ptr})) {
        # Welp, nothing to do here!
        return;
    }
    Blerg::Database::_close($obj->{ptr});
    delete $obj->{ptr};
}

DESTROY {
    my ($obj) = @_;
    $obj->close;
}

sub record_count {
    my ($obj) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_get_record_count($obj->{ptr});
}

sub set_subscription_mark {
    my ($obj) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_set_subscription_mark($obj->{ptr});
}

sub get_subscription_mark {
    my ($obj) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_get_subscription_mark($obj->{ptr});
}

sub subscription_list {
    my ($obj) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_subscription_list($obj->{name}, 0, 1);
}

sub mute {
    my ($obj, $v) = @_;
    $obj->_ensure_pointer;
    if (defined $v) {
        return Blerg::Database::_set_status($obj->{ptr}, $obj->BLERGSTATUS_MUTED, $v);
    } else {
        return Blerg::Database::_get_status($obj->{ptr}, $obj->BLERGSTATUS_MUTED);
    }
}

sub mention {
    my ($obj, $v) = @_;
    $obj->_ensure_pointer;
    if (defined $v) {
        return Blerg::Database::_set_status($obj->{ptr}, $obj->BLERGSTATUS_MENTIONED, $v);
    } else {
        return Blerg::Database::_get_status($obj->{ptr}, $obj->BLERGSTATUS_MENTIONED);
    }
}

sub refs {
    my ($obj) = @_;
    return Blerg::Database::tag_list('@' . $obj->{name}, 50, -1);
}

sub store {
    my ($obj, $data) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_store($obj->{ptr}, $data);
}

sub fetch {
    my ($obj, $record) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_fetch($obj->{ptr}, $record);
}

sub timestamp {
    my ($obj, $record) = @_;
    $obj->_ensure_pointer;
    return Blerg::Database::_get_timestamp($obj->{ptr}, $record);
}

# Convenience shortcuts
sub hash_tag_list {
    my ($name, $str_offset, $direction) = @_;
    return Blerg::Database::tag_list("#$name", $str_offset, $direction);
}

sub ref_tag_list {
    my ($name, $str_offset, $direction) = @_;
    return Blerg::Database::tag_list("@$name", $str_offset, $direction);
}

# Autoload methods go after =cut, and are processed by the autosplit program.

1;
__END__

=head1 NAME

=encoding utf8

Blerg::Database - Perl extension for reading Blërg! databases

=head1 SYNOPSIS

  use Blerg::Database;

  my $blerg = Blerg::Database->open_existing('foo');
  my $record = $blerg->post('This is some data!');
  $blerg->fetch($record);

=head1 DESCRIPTION

Blerg::Database is a utility library wrapping the core Blërg! database.  It
provides nicer OO wrappers around the core C library that powers Blërg!.

=head1 MODULE FUNCTIONS

=over

=item exists(name)

Returns 1 if the named database exists, or C<undef> if it doesn't.

=item tag_list(tag, offset, direction)

Returns a list of hashrefs describing blerg posts related to the given tag.
C<tag> includes the leading '@' or '#'.  Each item has two keys, C<author> and
C<record>.

=item hash_tag_list(name, offset, direction)

Convenience for C<tag_list> so that you don't have to prepend '#' to the name.

=item ref_tag_list(name, offset, direction)

Convenience for C<tag_list> so that you don't have to prepend '@' to the name.

=item subscription_add(from, to)

Adds a subscription from C<from> to C<to>.

=item subscription_remove(from, to)

The opposite of subscription_add.

=item valid_tag_name(name)

Validates that C<name> is a valid tag name.

=item valid_name(name)

Validates that C<name> is a valid username.

=back

=head1 CONSTRUCTOR

=over

=item open(name)

Opens the named database, creating it if it doesn't exist.

=item open_existing(name)

Opens the named database.  If it doesn't exist, returns C<undef>.

=back

=head1 CLASS METHODS

=head2 RECORDS

=over

=item record_count()

Returns the number of records in the database.

=item store(data)

Stores a new record containing C<data>.  Returns the record number of the new
record.

=item fetch(record)

Fetches a record from the database.

=item timestamp(record)

Returns a unix epoch timestamp for when the record was created.

=back

=head2 SUBSCRIPTIONS

=over

=item set_subscription_mark()

Mark all items on the subscription list as read.

=item get_subscription_mark()

Return the subscription list mark.

=item subscription_list()

Return a list of hashrefs describing posts in your subscription feed.  Each
hashref has a C<author> and C<record> key.

=back

=head2 REFS, MUTE, CLEANUP

=over

=item refs()

Convenience for listing references to the database.  Equivalent to
C<tag_list('@' . $obj-E<gt>{name})>.

=item mute(v)

When v = 1, mute the user, otherwise, unmute.  If v is absent, return the mute status.

=item close()

Closes the database.

=back

=head1 SEE ALSO

See the Blërg! website at http://blerg.cc.  More detailed docs about the
database internals are available in the source repo under www/doc, or at
http://blerg.cc/doc/

=head1 AUTHOR

Chip Black, E<lt>bytex64@bytex64.netE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2013 by Chip Black

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.16.1 or,
at your option, any later version of Perl 5 you may have available.

=cut
