#  Copyright (c) 1997-2018
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
#  http://www.polymake.org
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation; either version 2, or (at your option) any
#  later version: http://www.gnu.org/licenses/gpl.txt.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#-------------------------------------------------------------------------------
#
#  This file is part of the polymake database interface polyDB.
#
#   @author Silke Horn, Andreas Paffenholz
#   http://solros.de
#   http://www.mathematik.tu-darmstadt.de/~paffenholz
#

use namespaces qw(+ PolyDB);

CREDIT polyDB

declare $test_col_re = qr{test-.*?-\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}}xo;


# @category Database Admin
# This function cleans up everything (failed) testcases may have left in the Test database.
# @option Bool local set to 1 if you want to use a local database (on localhost), default 0
# @option String db database name
# @option String username database username
# @option String password database password
# @option String col column id to clean up
function db_clean_up_test ({local=>0, db=>"Test", username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd, collection=>undef}) {
    my ($options) = @_;

    my $client = Client::get_client($options);
    my $db = $client->get_database($options->{db});

    my @cols = defined($options->{collection}) ? ($options->{collection}) : $db->collection_names;
    my $i = 0;

    # drop collections that were created by testcases
    foreach (@cols) {
        if ($_ =~ $test_col_re) {
            $db->get_collection($_)->drop();
        }
    }

    # remove type information created by testcases
    my $collection = $db->get_collection("$PolyDB::default::db_type_information");
    $collection->delete_one({"col" => defined($options->{collection}) ? $options->{collection} : $test_col_re});
}

# @category Database Admin
# This function cleans up everything (failed) testcases may have left in the Test database.
# @option Bool local set to 1 if you want to use a local database (on localhost), default 0
# @option String db database name
# @option String username database username
# @option String password database password
# @option String col column id to clean up
function db_drop_test_db ({local=>0, db=>"Test", username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd}){
    my ($options) = @_;

    my $client = Client::get_client($options);
    my $db = $client->get_database($options->{db})->drop();
}

# @category Database Admin
# This function cleans up everything (failed) testcases may have left in the Test database.
# @option Bool local set to 1 if you want to use a local database (on localhost), default 0
# @option String db database name
# @option String username database username
# @option String password database password
# @option String col column id to clean up
function db_drop_test_collection ({local=>0, db=>undef, collection=>undef, username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd}){
   my ($options) = @_;

   my $client = Client::get_client($options);
   if ( defined($options->{db}) && defined($options->{collection}) ) {
      my $db = $client->get_database($options->{db});
      $db->get_collection($options->{collection})->drop();
   }
}


function db_remove_db_info ({local=>0, info_db=>"polyDB_testing", db=>undef, id=>undef, polyDB_version=>undef,  username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd }) {
   my ($options) = @_;

   my $client = Client::get_client($options->{local},"","");
   my $db = $client->get_database($options->{info_db});
   my $collection = $db->get_collection($PolyDB::default::db_info_collection);

   my %db_query = ('$or' => [{"users"=>$options->{username}}, {"users"=>"polymake"}] );
   $db_query{"col"} = "db_info";
   if (defined($options->{db})) {
      $db_query{"db"} = $options->{db};
   }
   if (defined($options->{id})) {
      $db_query{"_id"} = $options->{id};
   }
   if (defined($options->{polyDB_version})) {
      $db_query{"polyDB_version"} = $options->{polyDB_version};
   }

   my $count = $collection->count(\%db_query);
   if ( $count == 0 ) {
      die "no such entry in info database\n";
   }
   if ( $count > 1 ) {
      die "entry not uniquely defined: count=$count\n";
   }

   $collection->delete_one(\%db_query);
}

function db_remove_collection_info ({local=>0, info_db=>"polyDB_testing", db=>undef, id=>undef, polyDB_version=>undef, collection=>"undef", username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd }) {
   my ($options) = @_;

   my $client = Client::get_client($options->{local},"","");
   my $db = $client->get_database($options->{info_db});
   my $collection = $db->get_collection($PolyDB::default::db_info_collection);

   my %db_query = ();
   if (defined($options->{db})) {
      $db_query{"db"} = $options->{db};
   }
   if (defined($options->{collection})) {
      $db_query{"col"} = $options->{collection};
   }
   if (defined($options->{id})) {
      $db_query{"_id"} = $options->{id};
   }
   if (defined($options->{polyDB_version})) {
      $db_query{"polyDB_version"} = $options->{polyDB_version};
   }

   my $count = $collection->count(\%db_query);
   if ( $count == 0 ) {
      die "no such entry in info database\n";
   }
   if ( $count > 1 ) {
      die "entry not uniquely defined: count=$count\n";
   }

   $collection->delete_one(\%db_query);
}


function read_json_for_id ( { local=>0, db=>"Test", username=>$PolyDB::default::db_user, password=>$PolyDB::default::db_pwd, collection=>undef, id=>undef } ) {
   my $options = shift;

   my $client = Client::get_client($options);
   my $db = $client->get_database($options->{db});
   my $query = { "_id" => $options->{"id"} };
   my $collection = $db->get_collection($options->{"collection"});
   my $output = $collection->find_one($query)
      // die "No such object in the database.\n";
   return $output;
}


# Local Variables:
# mode: perl
# cperl-indent-level:3
# indent-tabs-mode:nil
# End:
