# -*- tcl -*-
#
# This test suite tests some basic interactions from the nsf mongo
# interface with gridFS. It connects to mongoDB, opens a GridFS named
# "myfs" and inserts a file into the filesystems.  Run the script
# with the current directory of nsfmongo, such it can find the README
# file.
#
# After running the script, one can use the following command to
# inspect the content in the GridFS via the mongo shell
#
#    $ mongo
#    > use myfs
#    > show collections
#    > db.fs.files.find()
#
# or via the mongofiles interface:
#
#    $ mongofiles -d myfs list
#

package require nx::test
package require nsf::mongo

#
# First, as usual, open the connection to the mongo db
#
? {set mongoConn [::mongo::connect]} mongoc_client_t:0

#
# Open a GridFS in the mongo database "myfs" and use the usual prefix
# "fs", such GridFS names the collections "fs.chunks" and "fs.files".
#
? {set gridFS [::mongo::gridfs::open $mongoConn myfs fs]} mongoc_gridfs_t:0

set dir [file dirname [file dirname [info script]]]
set fn [glob -tails -directory $dir -- README.md]
? {llength $fn} 1
? {file readable [file join $dir $fn]} 1
set fileSize [file size $fn]

# gridfs::remove_file removes all files with the specified name
# multiple store operations create "revisions" with different uploadDates
::mongo::gridfile::delete $gridFS [list filename string $fn]

# get the fs.files collection 
set mongoColl [mongo::collection::open $mongoConn myfs fs.files]

#
# The current version of gridfs_store_file() is quite unfriendly,
# since it assumes that the file exists, and aborts otherwise. So, we
# perform the existence test here. 
#
# Store a known file:
#
? {::mongo::gridfile::create -source file $gridFS [file join $dir $fn] $fn text/plain} 1

#
# Open grid file, get some of its properties, and read it in chunks
# of 1000 bytes, and close it finally.

? {set f [mongo::gridfile::open $gridFS [list filename string $fn]]} mongoc_gridfs_file_t:0
? {mongo::gridfile::get_metadata $f} ""
? {mongo::gridfile::get_contentlength $f} [file size [file join $dir $fn]]
? {mongo::gridfile::get_contenttype $f} text/plain

? {
  set chunks 0
  while {1} {
    set chunk [mongo::gridfile::read $f 1000]
    puts "... read chunk length [string length $chunk]"
    if {[string length $chunk] > 0}   { incr chunks }
    if {[string length $chunk] < 1000} {
      break
    }
  }
  set chunks
} [expr {$fileSize/1000 + 1}]
? {mongo::gridfile::close $f} ""

#
# Access the files stored in the gridfs via plain query interface.
# (should be just one)
puts "\nAll Files:"
#puts [join [::mongo::collection::query $mongoColl {}] \n]
set nr1 [llength [::mongo::collection::query $mongoColl {}]]
? {expr {$nr1 > 0}} 1

# store one more copy
? {::mongo::gridfile::create -source file $gridFS [file join $dir $fn] $fn text/plain} 1


# we should have now one more entry:
set nr2 [llength [::mongo::collection::query $mongoColl {}]]
? {expr {$nr2 == $nr1 + 1}} 1
puts [join [::mongo::collection::query $mongoColl {}] \n]

#
# Get the file named README from the gridfs via plain query interface
#
? {set files [::mongo::collection::query $mongoColl \
		  [list filename string $fn] \
		  -opts { limit int64 1 }]
  llength [lindex $files 0]
} 18

#
# Extract the oid from the bson attributes
#
? {
  foreach {name type value} [lindex $files 0] {
    if {$name eq "_id"} {set oid $value; break}
  }
  expr {$oid ne ""}
} 1

#
# Add a dc:creator to the bson attributes 
# and update the entry in the gridfs
#
? {::mongo::collection::update $mongoColl [list _id oid $oid] \
       [concat [lindex $files 0] [list metadata document {dc:creator string "Gustaf Neumann"}]]
} ""
#
# Now we can use the gridfs interface to obtain the additional
# metadata as well
#
set f [mongo::gridfile::open $gridFS [list _id oid $oid]]
? {mongo::gridfile::get_metadata $f} "dc:creator string {Gustaf Neumann}"
mongo::gridfile::close $f

#
# close everything
#
::mongo::gridfs::close $gridFS
::mongo::collection::close $mongoColl
::mongo::close $mongoConn

#
# Local variables:
#    mode: tcl
#    tcl-indent-level: 2
#    indent-tabs-mode: nil
# End:
