# -*- tcl -*-
#
# This is a sample test set using the low-level (pure tcl) interface
# for inserting and querying tuples into MongoDB.
#
# No interface changes so far between mongodb interface between 2.1 and 2.2.
#
# Main differences in the query interface due to changes in the
# upstream c-driver interface between the interface in nsf 2.0.0 (old)
# and 2.1.0 (new):
#
# Simple Query:
#    old [::mongo::collection::query $mongoColl [list \$query document {projects string nsf}]]
#    new [::mongo::collection::query $mongoColl {projects string nsf}]
#
#    old [::mongo::collection::query $mongoColl [list \$query document {age document {$gt int 30}}]]
#    new [::mongo::collection::query $mongoColl {age document {$gt int 30}}]
#
# Sort:
#   old [::mongo::collection::query $mongoColl \
#	       [list \$query document {projects string nsf} \$orderby document {name int -1}]]
#   new [::mongo::collection::query $mongoColl \
#              {projects string nsf} \
#              -opts {sort document {name int -1}}]
# Projection:
#   old [::mongo::collection::query $mongoColl \
#           {$query document {age document {$gt int 30}}} \
#           -atts {name int 1 age int 1}]
#   new [::mongo::collection::query $mongoColl \
#	     {age document {$gt int 30}} \
#	     -opts {projection document {name int 1 age int 1}}]
#
# Skip:
#   old [::mongo::collection::query $mongoColl \
#	       [list \$query document {projects string nsf} \$orderby document {name int -1}] \
#              -skip 1 ]
#   new [::mongo::collection::query $mongoColl \
#                        {projects string nsf} \
#                        -opts {
#                          sort document {name int 1}
#                          skip int64 1
#                        }]
# Limit:
#   old [::mongo::collection::query $mongoColl \
#	       [list \$query document {projects string nsf} \$orderby document {name int -1}] \
#              -limit 1 ]
#   new [::mongo::collection::query $mongoColl \
#                        {projects string nsf} \
#                        -opts {
#                          sort document {name int 1}
#                          limit int64 1
#                        }]



package require nsf

puts stderr "PWD [pwd]"
puts stderr "auto_path $auto_path"
foreach p [lsort [package names]] {
   if {![catch {package present $p}]} {
      set l [format %-15s $p]
      puts stderr "loaded $l [package ifneeded $p [package require $p]]"
   }
}

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

#nsf::configure debug 2
#
# One might query the resulting tuples from the mongo shell via:
#
#    mongo
#    > use tutorial
#    > db.persons.find();
#

#set mongoConn [::mongo::connect -uri mongodb://127.0.0.1:27017/]
? {set mongoConn [::mongo::connect]} "mongoc_client_t:0"
puts "Connection: $mongoConn"



if {1} {
  
  #::mongo::collection::delete $mongoConn tutorial.persons {}
  # Drop old potentially old collection and
  # recreate it as a capped collection
  ::mongo::run -nocomplain $mongoConn tutorial {drop string persons}
  puts "\nCreate a capped collection:"
  ? {::mongo::run $mongoConn tutorial {
    create string persons
    capped bool 1 
    size int32 100000
  }} "ok double 1.0"

  ? {set mongoColl [::mongo::collection::open $mongoConn tutorial persons]} "mongoc_collection_t:0"
  puts "Collection: $mongoColl"

  ? {mongo::collection::count $mongoColl {}} 0


  puts "\nInserting a few tuples"
  ? {llength [::mongo::collection::insert $mongoColl \
		  [list name string Gustaf projects string nsf age int32 53]]} "12"

  ? {mongo::collection::count $mongoColl {}} 1

  ::mongo::collection::insert $mongoColl \
      [list name string Stefan projects string nsf]
  ::mongo::collection::insert $mongoColl \
      [list name string Victor a array {0 string "x" 1 string "y"} age int 31]

  ? {
    set r [::mongo::collection::insert $mongoColl \
	       [list name string Joe \
		    projects string abc \
		    age int32 23 \
		    classes array {0 document {$ref string courses $id oid 1}}]]
    string match "_id oid *" $r
  } 1

  ::mongo::collection::insert $mongoColl \
      [list name string Franz info document {x int 203 y int 102} age int 29 projects string gtat]
  ::mongo::collection::insert $mongoColl \
      [list name string Selim ts timestamp {1302945037 1} d date 1302947619279]

  ? {mongo::collection::count $mongoColl {}} 6

  puts stderr "\nCreate an index on name (ascending)"
  ? {::mongo::collection::index $mongoColl [list name int 1]} 1
}

puts stderr "\nFull content"
? {llength [::mongo::collection::query $mongoColl {}]} 6

puts stderr RESULT=[::mongo::collection::query $mongoColl {}]


puts stderr "\nProject members"
? {
  llength [::mongo::collection::query $mongoColl \
               {projects string nsf} \
               -opts {sort document {name int -1}}]
} 2

set all [::mongo::collection::query $mongoColl \
                     {projects string nsf} \
                     -opts {
                       sort document {name int 1}
                     }]
set first [::mongo::collection::query $mongoColl \
                        {projects string nsf} \
                        -opts {
                          sort document {name int 1}
                          limit int64 1
                        }]
set second [::mongo::collection::query $mongoColl \
                        {projects string nsf} \
                        -opts {
                          sort document {name int 1}
                          skip int64 1
                        }]
? {llength $all} 2
? {list [lindex $all 0]} $first
? {list [lindex $all 1]} $second

package req nx::mongo
nx::mongo::Class create C

set result [::mongo::run $mongoConn tutorial {distinct string persons key string name}]

puts stderr "\nDistinct Persons: [C bson pp $result]"


puts stderr "\nProject members of nsf sorted by name"
? {
  set r [lindex [::mongo::collection::query $mongoColl {projects string nsf} \
                     -opts {sort document {name int 1}}] 0]
  string match *Gustaf* $r
} 1

puts stderr "\nAge > 30 (all atts)"
? {
  set r [::mongo::collection::query $mongoColl {age document {$gt int 30}}]
  set _ [llength $r]-[llength [lindex $r 0]]
} 2-12


puts stderr "\nAge > 30 (projection on name and age, aside of _id)"
? {
  set r [::mongo::collection::query $mongoColl \
	     {age document {$gt int 30}} \
	     -opts {projection document {name int 1 age int 1}}]
  set _ [llength $r]-[llength [lindex $r 0]]
} 2-9

puts stderr "\nCount Age > 30"
? {::mongo::collection::count $mongoColl {age document {$gt int 30}}} 2

puts stderr "\nAge > 30 (all atts, via cursor interface)"
? {
  set cursor [::mongo::cursor::find $mongoColl \
		  {age document {$gt int 30}}]
  puts "Cursor: $cursor"
  set r0 [::mongo::cursor::next $cursor]
  set r1 [::mongo::cursor::next $cursor]
  set r2 [::mongo::cursor::next $cursor]
  ::mongo::cursor::close $cursor
  set _ [llength $r0]-[llength $r1]-[llength $r2]
} 12-12-0

puts stderr "\nAge > 30 (all atts, via cursor interface, tailable)"
? {
  set cursor [::mongo::cursor::find $mongoColl \
		  {age document {$gt int 30}} \
                  -opts {tailable boolean true}]
  if {$cursor ne ""} {
    set r ""
    while {1} {
      lappend r [::mongo::cursor::next $cursor]
      if {[lindex $r end] eq ""} break
    }
    ::mongo::cursor::close $cursor
    join [lmap x $r {llength $x}] -
  }
} 12-12-0

puts stderr "\nEmpty result (via cursor interface)"
? {
  set cursor [::mongo::cursor::find $mongoColl \
		  [list \$query document {age document {$gt int 300}}]]
  if {$cursor ne ""} {
    set r {}
    while {1} {
      lappend r [::mongo::cursor::next $cursor]
      if {[lindex $r end] eq ""} break
    }
    ::mongo::cursor::close $cursor
    join [lmap x $r {llength $x}] -
  }
} 0

puts stderr "\nArray 'a' contains 'x'"
? {llength [::mongo::collection::query $mongoColl \
                {a string "x"}]} 1

puts stderr "\nEmbedded document has some value (info.y > 100)"
? {llength [::mongo::collection::query $mongoColl \
		{info.y document {$gt int 100}}]} 1

puts stderr "\nProjects in {nsf gtat}"
? { llength [::mongo::collection::query $mongoColl \
		 {projects document {$in array {0 string nsf 1 string gtat}}}]} 3

puts stderr "\nName ~ /an/i"
? {
  set r [::mongo::collection::query $mongoColl \
             {name document {$regex regex {an i}}} \
             -opts {projection document {name int 1}}]
  set _ [llength $r]-[lindex [lindex $r 0] end]-[lindex [lindex $r 1] end]
} 2-Franz-Stefan


puts stderr "\nStatistics of $mongoColl"
set stats [::mongo::collection::stats $mongoColl]

? {expr [llength $stats] % 3 == 0} 1
? {expr [llength $stats] > 0} 1

if {[llength $stats] % 3 == 0} {
  puts [C bson pp $stats]
}



puts stderr "\nStatus"
set status [::mongo::status $mongoConn]
puts [C bson pp $status]

? {expr [llength $status] % 3 == 0} 1
? {expr [llength $status] > 0} 1

puts stderr "\nClose connection $mongoConn"
::mongo::close $mongoConn

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