#! /usr/bin/env python
"""
 ***************************************************************************
    Command line imgSeek database frontend
    ---------------------------------------
    begin                : <2003-01-29 03:12:14 rnc>
    copyright            : (C) 2003 by Ricardo Niederberger Cabral
    email                : nieder|at|mail.ru

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ***************************************************************************
"""

import getopt, sys,traceback,os
from string import *
from os import getcwd,sep
from os.path import isfile

try:
    from imgSeekLib import ImgDB,__version__
    from imgSeekLib.Settings import Env
except:
    traceback.print_exc()
    print "Unable to find one of the modules required. Make sure imgSeek was installed properly. "
    sys.exit()

descr={"add":{"switches":{"h":"Show this help.",
                          "r":"Recurse into subdirectories when adding a path",
                          "s":"Scan all database directories for new images, adding them.",
                          },
              "parms":{},
              "optparms":{"d":"Scan and add to database all images on this directory.",
                          "i":"Ignore images with this string on their path",
                          "z":"Ignore images smaller than this size (kb)",
                          "m":"Ignore images with a dimension smaller than this (pixels)",
                          "b":"Database to use. [~/.imgseek/img-db.iqd]",
                          }
              },
       "info":{"switches":{"m":"Dump all metadata for this image."
                           },
               "parms":{"i":"Image id",
                        "p":"Image filename (full path - slow)",
                        "f":"Image filename",
                        },
               "optparms":{"d":"Dump this metadata field.",
                           "b":"Database to use. [~/.imgseek/img-db.iqd]",
                           }
               },
       "remove":{"switches":{},
               "parms":{"i":"Image id",
                        },
               "optparms":{
                           "b":"Database to use. [~/.imgseek/img-db.iqd]",
                           }
               },
       "query":{"switches":{},
                "parms":{"i":"Image id",
                         "p":"Image filename (full path)",
                         "f":"Image filename"
                         },
                "optparms":{"r":"Number of results [10]",
                            "b":"Database to use. [~/.imgseek/img-db.iqd]",
                            }
                },
       "browse":{"switches":{"G":"List all groups",
                             "V":"List all volumes",
                             "F":"List all images on database",
                             },
                "parms":{},
                "optparms":{
                            "b":"Database to use. [~/.imgseek/img-db.iqd]",
                            }
                }
       }

def usage(what=None,doExit=1):
    if not what:
        print "Usage is \"%s [add|info|query|browse|remove] {options}\""%sys.argv[0]
        print "Try for example \"%s add -h\" to get help on Add options."%sys.argv[0]
        sys.exit()
    print "\"%s\" command options:"%what

    print "Switches:"
    if not len(descr[what]["switches"]): print "\t[None]"
    for s in descr[what]["switches"]:
        print "\t-"+s+"\t"+descr[what]["switches"][s]

    print "Parameters:"
    if not len(descr[what]["parms"]): print "\t[None]"
    for s in descr[what]["parms"]:
        print "\t-"+s+"\t"+descr[what]["parms"][s]

    print "Optional parameters:"
    if not len(descr[what]["optparms"]): print "\t[None]"
    for s in descr[what]["optparms"]:
        print "\t-"+s+"\t"+descr[what]["optparms"][s]

    if doExit:
        sys.exit()

def main():
    print "imgSeekCmd %s\n"%__version__
    if len(sys.argv)<=1:
        usage()

    cmd=sys.argv[1]
    cmd=lower(cmd)
    if cmd not in ["add","info","query","browse","remove"]:
        usage()
    fmt=""
    for k in descr[cmd]["switches"]: fmt=fmt+k
    for k in descr[cmd]["parms"]: fmt=fmt+k+":"
    for k in descr[cmd]["optparms"]: fmt=fmt+k+":"
    lfmt=[]
    try:
        opts, args = getopt.getopt(sys.argv[2:], fmt, lfmt)
    except getopt.GetoptError:
        usage(cmd)                      # print help information and exit
    if not opts: usage(cmd)
    # make list of supplied switches
    sw=""
    for o, a in opts:
        sw=sw+o[1:]
    db=os.path.expanduser(os.path.join("~",".imgseek","img-db.iqd")) # set default dbase full filename
    ## open default database
    dbdir=os.path.expanduser(os.path.join("~",".imgseek"))
    if not os.path.exists(dbdir): # make sure "~/.imgseek" exists
        try:
            os.mkdir(dbdir)
        except:
            print "Error creating ~/.imgseek for storing config and database. imgSeek will use ~/ instead"
            db=os.path.expanduser(os.path.join("~","img-db.iqd"))
    for o, a in opts:
        try:
            if o in ["-b"]: db=a
        except:
            import traceback
            traceback.print_exc()

    print "Using database file:%s"%db
    env=Env()
    curdb=ImgDB.ImgDB(env)
    try:
        curdb.opendb(db)
    except:
        print "Error opening database:",db
        sys.exit(1)

    if cmd=="add":
        dir=None
        i=None
        z=0
        s=None
        m=0
        r=None
        restr=ImgDB.AddFilter(env)
        for o, a in opts:
            try:
                if o in ["-h","--help"]: usage("add")
                if o in ["-d"]: dir=a
                if o in ["-r"]: r=1
                if o in ["-s"]: s=1
                if o in ["-i"]: restr.igntext=a
                if o in ["-z"]: restr.minsize=int(a)
                if o in ["-m"]: restr.mindim=int(a)
            except:
                pass
        if not dir and not s:
            print "You must either choose a path to add (-d) or tell it to scan for new images (-s)."
            sys.exit()
        # new files will be added to default volume and orphan group. TODO: make it an option
        if dir:
            print "Adding \"%s\" ..."%dir
            curdb.addDir(volid=1,path=dir,groupid=1,aborted=[],recursive=r,calledRecurs=-1,restr=restr)#igntext=i,minsize=z,mindim=m)
            print "Done adding directories."
        if s:
            print "Looking for new images..."
            curdb.refreshDB()
            print "Done refreshing database."
        print "Exiting..."
    ##################################################################
    if cmd=="info":
        m=None
        i=None
        p=None
        f=None
        d=None
        b=None
        for o, a in opts:
            try:
                if o in ["-m"]: m=1
                if o in ["-i"]: i=int(a)
                if o in ["-f"]: f=a
                if o in ["-p"]: p=a
                if o in ["-d"]: d=a
            except:
                traceback.print_exc()
        if f:
            curdb.syncFilenames()
            if curdb.filenamedict.has_key(f):
                i=curdb.filenamedict[f]
        if p:
            for id in curdb.img.keys():
                if curdb.img[id][0]==p:
                    i=id
        if not i:
            print "You must supply an image id or filename"
            sys.exit(1)
        print "-"*len(curdb.img[i][0])
        print curdb.img[i][0]
        print "-"*len(curdb.img[i][0])
        if m:
            mdict=curdb.meta[i]
            for k in mdict:
                print "%s: %s"%(k,mdict[k])
        if d:
            mdict=curdb.meta[i]
            if mdict.has_key(d):
                print "%s: %s"%(d,mdict[d])
        print "Done."
    ##################################################################
    if cmd=="query":
        r=10
        i=None
        p=None
        f=None
        b=None
        for o, a in opts:
            try:
                if o in ["-i"]: i=int(a)
                if o in ["-f"]: f=a
                if o in ["-p"]: p=a
                if o in ["-r"]: r=int(a)
            except:
                traceback.print_exc()
        if f:
            if isfile(getcwd()+sep+f):
                i=getcwd()+sep+f        # TODO0: add support for querying physical files outside current working dir.
            else:
                curdb.syncFilenames()   # only sync id<->filenames if necessary (ie. when querying imgs on db using ids)
                if curdb.filenamedict.has_key(f):
                    # note that files with the same filename but on distinct paths will match incorrectly
                    # (that is, only the first one to appear on this dict will match)
                    i=curdb.filenamedict[f]
        if p:
            if isfile(p):               # user supplied existing filename, recalculate signature and query (even though it may be already on db)
                i=p
            else:                       # supplied filename doesn't exist, perhaps it's on db (a removable volume perhaps), so try hard to find it's id
                for id in curdb.img.keys():
                    if curdb.img[id][0]==p:
                        i=id
        if not i:                       # ok, user didn't supply physical filename, now try to find this filename on db
            print "You must supply an image id or filename"
            sys.exit(1)
        if type(i) is str:              # user supplied local filename
            print "-"*len(i)
            print i
            print "-"*len(i)
            #queries image filename , must be a photo TODO1:add support for sketches
            res=curdb.queryImage(i,r,1,removeFirst = 0)
        else:
            print "-"*len(curdb.img[i][0])
            print curdb.img[i][0]
            print "-"*len(curdb.img[i][0])
            res=curdb.queryData(i,r)
        for rid,rsc in res:
            print "%f: %s [%d]" % (rsc, curdb.img[rid][0],rid)
        print "Done."
    ##################################################################
    if cmd=="remove":
        r=10
        i=None
        for o, a in opts:
            try:
                if o in ["-i"]: i=int(a)
            except:
                traceback.print_exc()
        if not i:
            print "You must supply an image id or filename"
            sys.exit(1)
        try:
            curdb.removeFile(i)
        except:
            traceback.print_exc()
            print "Error removing image."

        print "Image %d removed."%i
    ##################################################################
    if cmd=="browse":
        for o, a in opts:
            try:
                if o in ["-G"]:
                    print "List of groups"
                    print "id,name,description,parent id,#(child imgs),#(child groups)"
                    for gid in curdb.groups.keys():
                        dt=curdb.groups[gid]
                        print "%d,%s,%s,%d,%s,%s"%(gid,dt[0],dt[1],dt[2],str(len(dt[3])),str(len(dt[4])))
                if o in ["-V"]:
                    print "List of volumes"
                    print "id,name,description,base path,#(dirs)"
                    for gid in curdb.volumes.keys():
                        dt=curdb.volumes[gid]
                        print "%d,%s,%s,%s,%s"%(gid,dt[3],dt[2],dt[1],str(len(dt[0])))
                if o in ["-F"]:
                    print "List of files"
                    print "id,path,#(parent groups)"
                    for gid in curdb.img.keys():
                        dt=curdb.img[gid]
                        print "%d,%s,%s"%(gid,dt[0],str(len(dt[2])))
            except:
                traceback.print_exc()
        print "Done."
    try:
        curdb.closedb()
    except:
        traceback.print_exc()
        print "Error closing database"

if __name__ == "__main__":
    main()
