#!/usr/bin/python
# 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 sys
import os
import re
import dictlib

def usage():
    print """dict [options] word [word ...]

The 'dict' program connects to a server that supports the dictionary
protocol defined in RFC2229, and allows you to look up words in the
dictionary.

Options:
-a usr pwd  Authenticate using the given user name and password.
-c cstr     Identify the client as 'cstr'.
-d [db]     With 'db' == '?' or no 'db', display a list of databases
            and exit.
            Otherwise 'db' is the name of a database to search.
            'db' can also be the special databases '*' and '!'.
            '*' shows all matching entries in all databases.
            '!' shows all matching entries in the first database that has
            the word being searched for.
            The default is "!".
-i          Display server information and exit.
-m          Display matches instead of definitions.
-p port     Connect on the given port. The default is 2628.
-s server   Connect to the given server, default is "dict.org".
-S [strat]  With 'strat' == '?', or no 'strat', display a list of
            strategies and exit.
            Otherwise, use the given strategy to find the words. The
            default is 'exact'.

Additionally, if 'dict' is invoked as an executable beginning with 'thes',
it will use a default server of "dione.zcu.cz" and a default dictionary
of "moby-thesaurus".

The program will also attempt to open ~/.dict and read configuration data
from there. The format is:
#comment
opt=parms # this is not a comment

If an option expects multiple parameters, they are split on spaces, so if
you are using the "a" (authenticate) and your login or password contains
a space, you can use the "user" and "pass" options instead of "a".

For options that don't take parameters, simply specifying them will turn
the option on, regardless of what comes after the equals sign.

Example:
a=adam password
server=mydict.com
db=dict3"""
    sys.exit(1)

def main():
    if len(sys.argv)==1: usage()

    opts  = {"user":False, "pass":False, "client":"dict - www.adammil.net",
             "db":False, "info":False, "matches":False, "port":"2628",
             "server":False, "strat":"exact"}
    ones  = {"c":"client", "d":"db", "p":"port", "s":"server", "S":"strat"}
    nones = {"i":"info", "m":"matches"}

    try:
        conf = file("%s/.dict" % os.getenv("HOME"), "r")
        try:
            for line in conf.readlines():
                line = line.lstrip()
                if len(line)==0 or line[0]=="#": continue
                m = re.match("^(\w+)=\s*(.*?)\s*$", line)
                if m != None:
                    key = m.group(1)
                    val = m.group(2)
                    if ones.has_key(key): opts[ones[key]]=val
                    elif nones.has_key(key): opts[nones[key]]=True
                    elif key=="a":
                        parms = " ".split(val)
                        if len(parms)==2:
                            (opts["user"],opts["pass"]) = (parms[0],parms[1])
                        else: print "Invalid spec for 'a' key in config file."
                    else: "Print unknown key in config file: %s" % key
        except: print "Error loading config file ~/.dict"
    except: pass

    i = 1
    while i<len(sys.argv):
        arg = sys.argv[i]
        if arg=="--": break
        elif len(arg)>1 and arg[0]=='-':
            if ones.has_key(arg[1]):
                if (arg[1]=='d' or arg[1]=='S') and len(sys.argv)<=i+1:
                    opts[ones[arg[1]]]="?"
                else: opts[ones[arg[1]]]=sys.argv[i+1]
                i += 1
            elif nones.has_key(arg[1]):
                opts[nones[arg[1]]]=True
            elif arg[1]=='a':
                opts["user"] = sys.argv[i+1]
                opts["pass"] = sys.argv[i+2]
                i += 2
            else: usage()
        else: break
        i += 1

    if opts["server"]==False:
        if re.match(r"(^|.*/)thes[^/]*$", sys.argv[0]) != None:
            opts["server"] = "dione.zcu.cz"
            if opts["db"]==False: opts["db"] = "moby-thesaurus"
        else: opts["server"] = "dict.org"
    if opts["db"]==False: opts["db"]="!"

    d = dictlib.DictProto(opts["server"], int(opts["port"]))

    if opts["info"]:
        print d.GetServerInfo()
        sys.exit(0)
    elif opts["db"]=="?":
        for db,desc in d.ListDBs():
            print "%s\t%s" % (db,desc)
        sys.exit(0)
    elif opts["strat"]=="?":
        for db,desc in d.ListStrategies():
            print "%s\t%s" % (db,desc)
        sys.exit(0)

    if opts["client"]: d.Ident(opts["client"])
    if opts["user"]:
        if not d.Auth(opts["user"], opts["pass"]):
            print "WARNING: Authorization failed."

    while i<len(sys.argv):
        word = sys.argv[i]
        i += 1
        if len(word)==0: continue
        matches = d.MatchWord(word, opts["db"], opts["strat"])
        if len(matches)==0:
            print "!!! No matches for \"%s\" in dictionary \"%s\"" % \
                  (word,opts["db"])
        for m in matches:
            print "--- \"%s\" found in dictionary \"%s\"" % (m[1],m[0])
            if not opts["matches"]:
                ent = d.DefineWord(m[1], m[0])[0][1]
                print ent

main()
