###########################################################################
#
# dbutil::gdbml -- extends the dbutil::gdbm class by adding simple file
# locking so as to allow for multiple readers/writers (albeit slow and not
# supported over network filesystems)
#
# A component of the Greenstone digital library software
# from the New Zealand Digital Library Project at the 
# University of Waikato, New Zealand.
#
# Copyright (C) 2013
#
# 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 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###########################################################################

package dbutil::gdbml;

use strict;

use dbutil::gdbm;

BEGIN
{
  @dbutil::gdbml::ISA = ('dbutil::gdbm');
}

# -----------------------------------------------------------------------------
#   GDBM IMPLEMENTATION
# -----------------------------------------------------------------------------

sub open_infodb_write_handle
{
  my $infodb_file_path = shift(@_);
  my $opt_append = shift(@_);

  # note the use of locking enabled txt2db [jmt12]
  # also, we assume the path is correct to find the executable [jmt12]
  my $txt2db_exe = "txt2dbl" . &util::get_os_exe();
  my $infodb_file_handle = undef;
  my $cmd = "\"$txt2db_exe\"";
  if ((defined $opt_append) && ($opt_append eq "append")) {
      $cmd .= " -append";
  }
  $cmd .= " \"$infodb_file_path\"";

  if(!open($infodb_file_handle, "| $cmd"))
  {

      print STDERR "Error: Failed to open pipe to $cmd\n";
      print STDERR "       $!\n";
      return undef;
  }

  binmode($infodb_file_handle,":utf8");

  return $infodb_file_handle;
}


sub read_infodb_file
{
  my $infodb_file_path = shift(@_);
  my $infodb_map = shift(@_);

  # note the use of locking enabled db2txt [jmt12]
  open (PIPEIN, "db2txtl \"$infodb_file_path\" |") || die "couldn't open pipe from db2txt \$infodb_file_path\"\n";

  binmode(PIPEIN,":utf8");

  my $infodb_line = "";
  my $infodb_key = "";
  my $infodb_value = "";
  while (defined ($infodb_line = <PIPEIN>))
  {
    if ($infodb_line =~ /^\[([^\]]+)\]$/)
    {
      $infodb_key = $1;
    }
    elsif ($infodb_line =~ /^-{70}$/)
    {
      $infodb_map->{$infodb_key} = $infodb_value;
      $infodb_key = "";
      $infodb_value = "";
    }
    else
    {
      $infodb_value .= $infodb_line;
    }
  }

  close (PIPEIN);
}

sub read_infodb_keys
{
  die("[gdbmkeys] not implemented for parallel building");
}

sub set_infodb_entry
{
    my $infodb_file_path = shift(@_);
    my $infodb_key = shift(@_);
    my $infodb_map = shift(@_);
  
    # HTML escape anything that is not part of the "contains" metadata value
    foreach my $k (keys %$infodb_map) {
	  my @escaped_v = ();
	  foreach my $v (@{$infodb_map->{$k}}) {
	    if ($k eq "contains") {
		  push(@escaped_v, $v);
	    }
	    else {
		  my $ev = &ghtml::unescape_html($v);
		  push(@escaped_v, $ev);
	    }
	  }
	  $infodb_map->{$k} = \@escaped_v;
	}
	
    # Generate the record string
    my $serialized_infodb_map = &dbutil::convert_infodb_hash_to_string($infodb_map);
###    print STDERR "**** ser dr\n$serialized_infodb_map\n\n\n";

    # Store it into GDBM using 'txt2db -append' which despite its name
    # actually replaces the record if it already exists
    # note the use of locking enabled txt2db [jmt12]
    my $cmd = "txt2dbl -append \"$infodb_file_path\"";

    my $status = undef;
    if(!open(GOUT, "| $cmd"))
    {
	print STDERR "Error: gdbm::set_infodb_entry() failed to open pipe to: $cmd\n";
	print STDERR "       $!\n";
	$status = -1;
    }
    else {
	binmode(GOUT,":utf8");
	
	print GOUT "[$infodb_key]\n";
	print GOUT "$serialized_infodb_map\n";

	close(GOUT);
	$status = 0; # as in exit status of cmd OK
    }

    return $status;  
}

1;
