#!/usr/bin/python
'''Print a pinkdex.'''
__version__='$Rev: 240 $'

import sys, os, optparse

import mitsfs

parser = optparse.OptionParser(usage='usage: %prog [--datadex file]',
                               version='%prog '+'$Id: pinkdex.py 240 2007-12-02 05:36:31Z kcr $')
parser.add_option('-d', '--datadex', dest='dexfile',
                  help='datadex file to load (default %default)', default=mitsfs.datadex_file)
parser.add_option('-s', '--supplement', dest='suppl',
                  help='supplementary dex', default=None)
parser.add_option('-o', '--outfile', dest='outfile',
                  help='Output file', default=None)
options, args = parser.parse_args()

noboxed = True
if options.suppl or options.outfile:
    titledex = False
    seriesdex = False
    pinkdex = True
else:
    titledex = True
    seriesdex = True
    pinkdex = True

print 'loading...',
sys.stdout.flush()
dex = mitsfs.dex(options.dexfile)
print 'done.'

if os.getcwd() == mitsfs.dexbase:
    print 'Preemptively changing directory to /tmp; look for your pinkdexen there.'
    os.chdir('/tmp')

def book(line):
    series = [i.replace(',',r'\,') for i in line.series if i]
    titles = ['=' in i and i[:i.find('=')] or i for i in line.titles] # strip the sortbys
    if noboxed:
        unboxed = [(code, count)
                   for (code, count) in line.codes.items()
                   if mitsfs.codes[mitsfs.splitcode(code)[1]].get('box') not in ('all', 'kbx')]
        nboxed = [(code, count)
                  for (code, count) in line.codes.items()
                  if mitsfs.codes[mitsfs.splitcode(code)[1]].get('box') == 'all']
        if unboxed:
            codes = ','.join((count == 1 and code or r'%s\:%d' % (code, count)
                              for (code, count) in unboxed))
        elif nboxed:
            codes = r'\['+','.join((count == 1 and code or r'%s\:%d' % (code, count)
                                         for (code, count) in nboxed))+r'\]'
            boxed.append(line)
        else:
            codes = '*'
            kboxed.append(line)
    else:
        codes = str(line.codes).replace(':', r'\:')
    if series:
        if len(series) == len(titles):
            titles = ['%s [%s]' % i for i in zip(titles, series)]
        elif len(titles) == 1:
            titles = ['%s [%s]' % (titles[0], '|'.join(series))]
        elif len(series) == 1:
            titles = ['%s [%s]' % (i, series[0]) for i in titles]
        else:  # this is apparently Officially Weird
            print 'Wacky title/series match: ',str(line)
            ntitles = ['%s [%s]' % i for i in zip(titles, series)]
            if len(line.series) < len(titles):
                ntitles += titles[len(series):]
            titles = ntitles
    title = '|'.join(titles)
    args = [mitsfs.texquote(i) for i in [line.authortxt, title, codes]]
    return r'\Book'+''.join(['{%s}' % i for i in args])

if pinkdex:
    print 'sorting pinkdex...',
    sys.stdout.flush()
    books = list(dex)
    books.sort(key=lambda line: (line.placeauthor, line.placetitle))
    print 'done.'

    boxed = []
    kboxed = []
    print 'writing...',
    sys.stdout.flush()
    pinkfile = options.outfile or 'pinkdex.tex'
    fp = open(pinkfile, 'w')
    print >>fp,r'\def\dexname{Pinkdex}'
    if options.suppl:
        print >>fp,r'\def\Supple{%s}' % options.suppl
        print >>fp,r'\def\Period{3}'
    else:
        print >>fp,r'\def\Period{0}'
    print >>fp,r'\input %s/dextex-current.tex' % mitsfs.texbase
    # 	    ($opt{-by} eq "author" ? () : "\\def\\Reverse{}"),
    # 	    ($opt{-supple} ? "\\def\\Supple{$opt{-supple}}" : ()),
    letter = None
    for line in books:
        newletter = line.placeauthor[0]
        if letter != newletter:
            if letter is not None and not options.suppl:
                print >>fp,r'\NextLetter'
            letter = newletter
            print letter,
            sys.stdout.flush()
        print >>fp,book(line)
    print >>fp,r'\vfill \eject \bye'
    fp.close()
    print 'done.'
    if boxed:
        print 'Titles only boxed:'
        for i in boxed:
            print i
    if kboxed:
        print 'Titles only kboxed:'
        for i in kboxed:
            print i

if titledex:
    print 'sorting titledex...',
    sys.stdout.flush()
    books = list(dex)
    books.sort(key=lambda line: (line.placetitle, line.placeauthor))
    print 'done.'

    boxed = []
    kboxed = []
    print 'writing...',
    sys.stdout.flush()
    fp = open('titledex.tex', 'w')
    print >>fp,r"""\def\dexname{Titledex}
    \def\Reverse{}
    \def\Period{0}
    \input %s/dextex-current.tex""" % mitsfs.texbase
    # 	    ($opt{-by} eq "author" ? () : "\\def\\Reverse{}"),
    # 	    ($opt{-supple} ? "\\def\\Supple{$opt{-supple}}" : ()),
    letter = None
    for line in books:
        newletter = line.placetitle[0]
        if letter != newletter:
            if letter is not None:
                print >>fp,r'\NextLetter'
            letter = newletter
            print letter,
            sys.stdout.flush()
        print >>fp,book(line)
    print >>fp,r'\vfill \eject \bye'
    fp.close()
    print 'done.'

if seriesdex:
    print 'sorting seriesdex...',
    sys.stdout.flush()
    books = list(dex)
    books.sort(key=lambda line: (line.placeseries, line.placetitle, line.placeauthor))
    print 'done.'

    books = [i for i in books if i.series]
    boxed = []
    kboxed = []
    print 'writing...',
    sys.stdout.flush()
    fp = open('seriesdex.tex', 'w')
    print >>fp,r"""\def\dexname{Seriesdex}
    \def\Reverse{}
    \def\Period{0}
    \input %s/dextex-current.tex""" % mitsfs.texbase
    print >>fp
    print >>fp,r'\beginserieslist'
    series = dex.indices.series.items()
    series.sort()
    for s, l in series:
        print >>fp,r'	\Series{%s}{%s}{%d}' % (
            mitsfs.texquote(s),
            mitsfs.texquote(reduce(lambda a, b: a and b, [line.authors == l[0].authors for line in l]) and l[0].authortxt or 'authorship varies'),
            len(l)
            )
    print >>fp,r'\endserieslist'
    letter = None
    for line in books:
        newletter = line.placeseries[0]
        if letter != newletter:
            if letter is not None:
                print >>fp,r'\NextLetter'
            letter = newletter
            print letter,
            sys.stdout.flush()
        print >>fp,book(line)
    print >>fp,r'\vfill \eject \bye'
    fp.close()
    print 'done.'

