# ABSTRACT: ArangoDB Database object

package Arango::Tango::Database;
$Arango::Tango::Database::VERSION = '0.013';
use Arango::Tango::Cursor;
use Arango::Tango::API;

use warnings;
use strict;

BEGIN {
    Arango::Tango::API::_install_methods "Arango::Tango::Database" => {

        delete_collection => {
            rest => [ delete => '{{database}}_api/collection/{colname}' ],
            signature => [ 'colname' ],
            inject_properties => [ { prop => 'name', as => 'database' } ],
        },

        get_indexes => {
            rest => [ get => '{{database}}_api/index?collection={colname}' ],
            signature => [ 'colname' ],
            inject_properties => [ { prop => 'name', as => 'database' } ]
        },

        create_ttl_index => {
            rest => [ post => '{{database}}_api/index?collection={colname}' ],
            signature => [ 'colname' ],
            inject_properties => [ { prop => 'name', as => 'database' } ],
            schema => {
                name => { type => 'string' },
                type => { type => 'string', enum => ['ttl'] },
                fields => { type => 'array', items => { type => 'string' } },
                expireAfter => { type => 'integer' }
            }
        },

        create_collection => {
            rest => [ post => '{{database}}_api/collection' ],
            schema => {
                keyOptions => { type => 'object', additionalProperties => 0, params => {
                    allowUserKeys => { type => 'boolean' },
                    type          => { type => 'string', default => 'traditional', enum => [qw'traditional autoincrement uuid padded'] },
                    increment     => { type => 'integer' },
                    offset        => { type => 'integer' },
                }},
                journalSize       => { type => 'integer' },
                replicationFactor => { type => 'integer' },
                waitForSync       => { type => 'boolean' },
                doCompact         => { type => 'boolean' },
                shardingStrategy  => {
                    type    => 'string',
                    default => 'community-compat',
                    enum    => ['community-compat', 'enterprise-compat', 'enterprise-smart-edge-compat', 'hash', 'enterprise-hash-smart-edge']},
                isVolatile        => { type => 'boolean' },
                shardKeys         => { type => 'array', items => {type => 'string'} },
                numberOfShards    => { type => 'integer' },
                isSystem          => { type => 'booean' },
                type              => { type => 'string', default => '2', enum => ['2', '3'] },
                indexBuckets      => { type => 'integer' },
                distributeShardsLike => { type => 'string' },
                name              => { type => 'string' }
            },
            builder => sub {
                my ($self, %params) = @_;
                return Arango::Tango::Collection->_new(arango => $self, database => $params{database}, 'name' => $params{name});
            },
            signature => [ 'name' ],
            inject_properties => [ { prop => 'name', as => 'database' } ]
        }

    };
}

sub _new {
    my ($class, %opts) = @_;
    return bless {%opts} => $class;
}

sub delete {
    my $self = shift;
    return $self->{arango}->delete_database($self->{name});
}

sub cursor {
    my ($self, $aql, %opts) = @_;
    return Arango::Tango::Cursor->_new(arango => $self->{arango}, database => $self->{name}, query => $aql, %opts);
}





sub collection {
   my ($self, $name) = @_;
   my @match = grep { $_->{name} eq $name } @{$self->list_collections};
   if (scalar(@match)) {
      return Arango::Tango::Collection->_new(arango => $self->{arango}, database => $self->{name}, 'name' => $name);
   }
   else {
      die "Arango::Tango | Collection not found in database $self->{name}."
   }
}

sub list_collections {
    my ($self, %opts) = @_;
    return $self->{arango}->_api( list_collections => {  %opts, database => $self->{name} } )->{result};
}


sub get_access_level {
    my ($self, $username, $collection) = @_;
    return $self->{arango}->get_access_level( $username, $self->{name}, $collection);
}

sub clear_access_level {
    my ($self, $username, $collection) = @_;
    return $self->{arango}->clear_access_level($username, $self->{name},  $collection);
}

sub set_access_level {
    my ($self, $username, $grant, $collection) = @_;
    return $self->{arango}->set_access_level($username, $grant, $self->{name},  $collection);
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Arango::Tango::Database - ArangoDB Database object

=head1 VERSION

version 0.013

=head1 USAGE

This class should not be created directly. The L<Arango::Tango> module is responsible for
creating instances of this object.

C<Arango::Tango::Database> answers to the following methods:

=head2 C<list_collections>

   my $cols = $database->list_collections;

Returns an array reference to the collections available in the database.

=head2 C<create_collection>

   my $col = $database->create_collection("col_name");

Creates a new collection and returns the object representing it (L<Arango::Tango::Collection>).

=head2 C<collection>

    my $collection = $database->collection("some_collection");

Opens an existing collection, and returns a reference to a L<Arango::Tango::Collection> representing it.

=head2 C<delete_collection>

   $database->delete_collection("col_name");

Deletes a collection.

=head2 C<cursor>

   my $cursor = $database->cursor( $aql_query, %opt );

Performs AQL queries, returning a cursor. An optional hash of
options can be supplied. Supported hashes corresponde to the different attributes
available in the ArangoDB REST API (L<https://docs.arangodb.com/3.4/HTTP/AqlQueryCursor/AccessingCursors.html>).

=head2 C<delete>

    $db->delete;

Deletes the supplied database.

=head2 C<get_access_level>

    $perms = $db->get_access_level($user)
    $perms = $db->get_access_level($user, $collection)

Fetch the database or collection access level for a specific user.

=head2 C<set_access_level>

    $db->set_access_level($user, "rw")
    $db->set_access_level($user, "ro", $collection)

Set the database or collection access level for a specific user.

=head2 C<clear_access_level>

    $db->clear_access_level($user)
    $db->clear_access_level($user, $collection)

Clears the database or collection access level for a specific user.

=head2 C<get_indexes>

   $idxs = $db->get_indexes("col_name");

Returns an object containing an array reference with the details
of the indexes presently defined for the given collection.

=head2 C<create_ttl_index>

   $idx = $db->create_ttl_index("col_name", %args);

Creates a new index of type ttl for the given collection. The
mandatory args are "type" (must be "ttl"), "name" (string,
human name for the index), "fields" (array ref with the
names of the document fields to be used as expiration timestamps)
and "expireAfter" (integer, seconds).
Returns an object containing the id of the created index and the
confirmation of the provided arguments ("type", "name", "fields"
and "expireAfter"). If an error occurs the error field will be
true, otherwise false.

=head1 AUTHOR

Alberto Simões <ambs@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2019-2020 by Alberto Simões.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut