#!/usr/bin/env tclsh
#
#   Dionysus is a search engine for scientific constants and 
#   engineering parameters.
#
#   Copyright (C) 2009 Jean Michel Sellier
#   <jeanmichel.sellier@gmail.com>
# 
#   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 3, 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, see <http://www.gnu.org/licenses/>.
#
# created : 08 sep.2009, Jean Michel Sellier, West Lafayette, IN, USA
# last modified : 05 dec.2009, JM Sellier, Cassibile (SR), Italy
#
# how to use this command
# > ./dionysus DB.ddb value_name option
# for more informations type
# > ./dionysus --help
# to list the values in a database
# > ./dionysus DB.ddb --list-values FORMAT
# where FORMAT is HTML or ASCII

# help option
if {[lindex $argv 0]=="--help" || [lindex $argv 0]=="--h"} {
 puts "Usage:"
 puts "> dionysus DB.bb constant_name info"
 puts "to know the info of constant_name in DB.bb database."
 puts ""
 puts "> dionysus DB.bb --list-values FORMAT"
 puts "to see the complete list of constants in the specified FORMAT in DB.bb database."
 puts ""
 puts ">dionysus --version"
 puts "to see the version of this package."
 puts ""
 puts "> dionysus --help"
 puts "to see this help message."
 puts ""
 puts "Example:"
 puts "> dionysus databases/universal.ddb electron_mass value"
 puts ""
 exit 1
}

# version option
if {[lindex $argv 0]=="--version" || [lindex $argv 0]=="--v"} {
 puts "Dionysus version 1.2.0"
 puts ""
 puts "Copyright (C) 2009 Sellier Jean Michel."
 puts "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A"
 puts "PARTICULAR PURPOSE."
 puts "You may redistribute copies of GNU Dionysus under the terms"
 puts "of the GNU General Public License."
 puts "For more information about these matters, see the file named COPYING."
 puts ""
 exit 1
}

# check the number of specified arguments
set num [llength $argv]
if {$num!=3} {
 puts "the number of arguments is wrong."
 puts "please use --help option for more informations."
 exit 1
}

# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# THIS IS WHERE THE --list-values OPTION IS IMPLEMENTED
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if {[lindex $argv 1]=="--list-values"} {

 # check if the specified format is valid
 # (for now the onlly two valid formats are ASCII and HTML)
 set format [string tolower [lindex $argv 2]]
 if {$format!="ascii" && $format!="html"} {
  puts "this format is not supported."
  puts "the supported formats are:"
  puts "- ASCII"
  puts "- HTML"
  exit 1
 }

 # check and open the specified ASCII DB file
 if { [catch {set fp [open [lindex $argv 0] "r"]}]} {
  puts "the specified DB file does not exist or cannot be open"
  close $fp
  exit 1
 }

 # read the entire file in a string
 set data [read $fp]
 if {$data==""} {
  puts "the specified DB file is empty!"
  close $fp
  exit 1
 }

 # close the file properly
 close $fp

 # split the entire variable "data" into single rows
 set rows [split $data "\n"]
 if {$format=="ascii"} {
  puts "Item(s) founds in the database:"
  puts "-------------------------------"
 }
 if {$format=="html"} {
  set dum [lindex $argv 0]
  puts "<html><h3>Database: $dum</h3><table border=2>"
  puts "<tr><td>Name(s)</td><td>Value</td><td>Units</td><td>Description</td></tr>"
 }

 # set the counter to zero
 set counter 0

 # split every row and check if they start by a "def" tag
 foreach row $rows {
  set constname ""
  set splitted [split $row "="]
  set first [string tolower [lindex $splitted 0]]
  set dummy [split $first " "]
  foreach elem $dummy {
   if {$elem=="name" && $format=="ascii"} {
    incr counter
    set minilist [split [lindex $splitted 1] "\""]
    foreach minielem $minilist {
     if {[lsearch $minielem "||"]==-1 && $minielem!=""} {
      puts -nonewline "-- $minielem --  "
     }
    }
    puts ""
   }; # end of ASCII format
   if {$elem=="name" && $format=="html"} {
    incr counter
    set minilist [split [lindex $splitted 1] "\""]
    puts "<tr><td>"
    set cc 0
    foreach minielem $minilist {
     if {[lsearch $minielem "||"]==-1 && $minielem!=""} {
      global constname
      global cc
      if {$cc=="0"} {
       set constname $minielem
      }
      incr cc
      puts "$minielem<br>"
     }
    }
    puts "</td>"
    set dbname [lindex $argv 0]
    # show the value
    exec dionysus $dbname $constname value > dum.out
    set fp [open "dum.out" "r"]
    set dum [read -nonewline $fp]
    if {$dum==""} {
     global dum
     set dum "not specified"
    }
    close $fp
    puts "<td> $dum </td>"
    # show the units
    exec dionysus $dbname $constname units > dum.out
    set fp [open "dum.out" "r"]
    set dum [read -nonewline $fp]
    if {$dum==""} {
     global dum
     set dum "not specified"
    }
    close $fp
    puts "<td> $dum </td>"
    # show the description
    exec dionysus $dbname $constname description > dum.out
    set fp [open "dum.out" "r"]
    set dum [read -nonewline $fp]
    if {$dum==""} {
     global dum
     set dum "not specified"
    }
    close $fp
    puts "<td> $dum </td>"
    puts "</tr>"
   }; # end of HTML format
  }
 }

 # eventually remove auxiliary files
 exec rm -rf dum.out

 # show the number of found items or created files
 if {$format=="ascii"} {
  puts "the number of found items is: $counter"
 }
 if {$format=="html"} {
  puts "</table>"
  puts "<h3>the number of items in the database is: $counter</h3>"
  puts "</html>"
 }

 # if we are here everything went fine
 exit 0
}

# END OF --list-values OPTION

# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# THIS IS WHERE THE QUERY IS PROCESSED
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

# check and open the specified ASCII DB file
if { [catch {set fp [open [lindex $argv 0] "r"]}]} {
 puts "the specified DB file does not exist or cannot be open"
 exit 1
}

# once we are sure the file exists we scan it
# value name and property
set specname [string tolower [lindex $argv 1]]
set property [string tolower [lindex $argv 2]]

# read the entire file in a string
set data [read $fp]
if {$data==""} {
 puts "the specified DB file is empty!"
 exit 1
}

# split the entire variable "data" into single rows
set rows [split $data "\n"]

# scan every single row and look for what is required
set found 0
set namef 0
for {set i 1} {$i<=[llength $rows]} {incr i} {
 global found
 global namef
 set row [lindex $rows [expr $i-1]]
 # search for an eventual definition
 # parse the row only if it's not a comment
 if {[lindex [split $row " "] 0]!="#"} {
  foreach dum [split $row " "] {
   if {[string tolower $dum]=="def"} {
    # if there is a "def" which does not finish by a "end" then error
    if {$found==1} {
     puts "The DB is not defined correctly. Row $i is \"def\" while it should be \"end\"."
     exit 1
    } else {
     # if everything is all right then set the flag to 1
     set found 1
    }
   }
  }

  # the following row is needed by both "property" and "value"
  set commands [split $row "="]

  # if the word is $property
  if {$namef==1} {
   set comand [split [lindex $commands 0] " "]
   if {[string tolower [lindex $comand 2]]==[string tolower $property]} {
    set ret [lindex $commands 1]
    set primo  [expr [string first "\"" $ret]+1]
    set ultimo [expr [string last "\"" $ret]-1]
    puts [string range $ret $primo $ultimo]
    set $namef 0
    exit 0
   }
  }
  # look for the name of the variable
  if {[string first "name" [string tolower [lindex $commands 0]]]!=-1 && $namef==0} {
   set names [lindex [split $row "="] 1]
   foreach name [split $names "||"] {
    set name [string tolower $name]
    # toggles the double quotes in names
    set primo  [expr [string first "\"" $name]+1]
    set ultimo [expr [string last "\"" $name]-1]
    # "nome" is "name" without the initial and final double quotes
    set nome [string range $name $primo $ultimo]
    if {$nome==$specname} {
     set namef 1
    }
   }
  }
  # if the word is "end"
  foreach dum [split $row " "] {
   if {[string tolower $dum]=="end"} {
    set found 0
    set namef 0
   }
  }
 }
}

close $fp
exit 0

# END OF QUERY PROCESSING
