#! /usr/bin/env python

# XXX find paths to libraries and system databases using kpsewhich
version = 'Testing'
xtxlib = 'lib'
plylib = '/usr/local/lib/crosstex'

import sys
sys.path.append(xtxlib)
if plylib not in sys.path:
  sys.path.append(plylib)

import copy
import math
import pipes
import re
import optparse
import string
import tempfile
import imp
import os.path

from crosstex.options import OptionParser, warning, error
from crosstex.resolve import Database
from crosstex.parse import Parser
import crosstex.style.common
import crosstex.objects


optparser = OptionParser(version, [xtxlib])
namearg = '--' + os.path.basename(sys.argv[0])
if optparser.has_option(namearg):
  sys.argv.insert(1, namearg)

opts, files = optparser.parse_args()
if not files:
  optparser.print_help()
  sys.exit(0)

dbparser = Parser(opts, optparser)
paths = dbparser.files(files)
path = '.'.join([os.path.splitext(paths[-1])[0], opts.convert])
dbparser.parse('standard')
try:
  if opts.convert == 'html':
    t = pipes.Template()
    t.append('hevea -O', '--')
    out = t.open(path, 'w')
  else:
    out = open(path, 'w')
except IOError, details:
  error(opts, 'Unable to open output file "%s": %s.' % (path, details))
  sys.exit(opts.errors)

if opts.style is None:
  if opts.convert == 'bbl':
    opts.style = 'plain'
  else:
    opts.style = opts.convert
try:
  # XXX Use kpathsea
  mod = None
  try:
    mod = imp.find_module(opts.style, [os.path.basename(path)])
    stylemodule = imp.load_module(opts.style, *mod)
  finally:
    if mod and mod[0]:
      mod[0].close()
except ImportError, details:
  try:
    stylemodule = __import__('crosstex.style.' + opts.style)
    stylemodule = getattr(stylemodule.style, opts.style)
  except ImportError, details:
    error(opts, 'Can not load %s style: %s\n' % (opts.style, details))
    sys.exit(opts.errors)
if opts.style in ['unsrt', 'ieeetr']:
  dbparser.addopts(['--no-sort'])
if opts.style == 'html':
  dbparser.addopts(['--blank-labels', '--break-lines'])
  if opts.link == []:
    dbparser.addopts(['-l', 'Abstract', '-l', 'URL', '-l', 'PS', '-l',
                      'PDF', '-l', 'HTML', '-l', 'DVI', '-l', 'TEX', '-l',
                      'BIB', '-l', 'FTP', '-l', 'HTTP', '-l', 'RTF'])
for kind in opts.capitalize:
  getattr(crosstex.objects, kind)._addfilter(crosstex.style.common.uppercasefilter, 'value')
for field in opts.no_field:
  crosstex.objects.publication._addfilter(crosstex.style.common.killfilter, field)
if opts.add_in:
  crosstex.objects.publication._addfilter(crosstex.style.common.infilter, 'fullpublication', 'booktitle')
  crosstex.objects.publication._addfilter(crosstex.style.common.infilter, 'fullpublication', 'journal')
if opts.add_proc:
  crosstex.objects.conference._addfilter(crosstex.style.common.procfilter, 'value')
if opts.add_proceedings:
  crosstex.objects.conference._addfilter(crosstex.style.common.proceedingsfilter, 'value')
if dbparser.titlephrases and opts.titlecase != 'upper':
  crosstex.objects.publication._addfilter(crosstex.style.common.maketitlephrasefilter(dbparser.titlephrases), 'title')
if dbparser.titlesmalls and opts.titlecase != 'upper':
  crosstex.objects.publication._addfilter(crosstex.style.common.makelowerphrasefilter(dbparser.titlesmalls), 'title')
if opts.titlecase == 'lower':
  crosstex.objects.publication._addfilter(crosstex.style.common.lowertitlecasefilter, 'title')
elif opts.titlecase == 'upper':
  crosstex.objects.publication._addfilter(crosstex.style.common.uppercasefilter, 'title')
elif opts.titlecase == 'default':
  crosstex.objects.publication._addfilter(crosstex.style.common.titlecasefilter, 'title')
if opts.last_first:
  crosstex.objects.publication._addlistfilter(crosstex.style.common.lastfirstlistfilter, 'author')
  crosstex.objects.publication._addlistfilter(crosstex.style.common.lastfirstlistfilter, 'editor')
if opts.link:
  crosstex.objects.publication._addproducer(crosstex.style.common.makelinksproducer(opts.link), 'links')
if opts.abstract or opts.keywords:
  crosstex.objects.publication._addproducer(crosstex.style.common.extrasproducer, 'extras')
  if not opts.abstract:
    crosstex.objects.publication._addfilter(crosstex.style.common.killfilter, 'extras', 'abstract')
  if not opts.keywords:
    crosstex.objects.publication._addfilter(crosstex.style.common.killfilter, 'extras', 'keywords')
if opts.title_head:
  crosstex.objects.publication._addfilter(crosstex.style.common.boldfilter, 'fulltitle')
if opts.cite_by == 'number':
  crosstex.objects.publication._addproducer(crosstex.style.common.emptyproducer, 'label')
elif opts.cite_by == 'initials':
  crosstex.objects.publication._addproducer(crosstex.style.common.makegetterproducer('initialslabel'), 'label')
elif opts.cite_by == 'fullname':
  crosstex.objects.publication._addproducer(crosstex.style.common.makegetterproducer('fullnamelabel'), 'label')
if opts.title_head:
  crosstex.objects.publication._addproducer(crosstex.style.common.makejoinproducer(".", "\n\\newblock ", ".", "", 'fulltitle', 'fullauthorpublicationextras'), 'value')
for kind in opts.short:
  getattr(crosstex.objects, kind)._addproducer(crosstex.style.common.makegetterproducer('shortname'), 'value')
  if kind in ['author', 'editor']:
    crosstex.objects.publication._addlistfilter(crosstex.style.common.shortnameslistfilter, kind)

db = Database(dbparser)

for kind in opts.dump:
  if kind in ['file', 'titlephrase', 'titlesmall']:
    continue
  entries = db.dump(kind)
  if entries:
    sys.stderr.write('\n%s:\n' % kind.upper())
    entries.sort()
    for entry in entries:
      sys.stderr.write('%s\n' % entry)
  else:
    sys.stderr.write('No %s objects defined.\n' % kind)
if 'titlephrase' in opts.dump and db.titlephrases:
  sys.stderr.write('\nTITLE PHRASES:\n')
  for phrase in db.titlephrases:
    sys.stderr.write('%s\n' % phrase)
if 'titlesmall' in opts.dump:
  sys.stderr.write('\nTITLE SMALL WORDS:\n')
  for small in db.titlesmalls:
    sys.stderr.write('%s\n' % small)

if opts.convert == 'html':
  out.write("\\documentclass{report}\n")
  out.write("\\usepackage{hyperref}\n")
  out.write("\\newstyle{.dt-list}{margin-top:1em}\n")
  if opts.popups:
    out.write("\\newstyle{.dd-list}{position:relative}\n")
    out.write("\\newstyle{.dd-list .quotation}"
              "{visibility:hidden;position:absolute;top:100\%;"
              "left:4em;margin-top:-1em;padding:1em;"
              "border:1px solid \#aaaaaa;background:\#ffffff;"
              "z-index:1}\n")
    out.write("\\newstyle{.dd-list .quotation *}"
              "{margin-left:0;padding-left:0}\n")
    out.write("\\newstyle{.dd-list:hover .quotation}"
              "{visibility:visible}\n")
  out.write("\\begin{document}\n")
if opts.convert == 'html' or opts.convert == 'bbl':
  for i in db.preambles:
    out.write(i + '\n')
  if opts.blank_labels:
    out.write("\\makeatletter\\def\\@biblabel#1{}\\makeatother\n")
  if opts.break_lines:
    out.write("\\renewcommand{\\newblock}{\\\\}")
  out.write("\\newcommand{\\etalchar}[1]{$^{#1}$}\n")
if opts.convert == 'bib' or opts.convert == 'xtx':
  for i in db.preambles:
    out.write('@PREAMBLE { "%s" }\n\n' % i)

#if opts.convert != 'xtx' and len(opts.heading) > 1:
#  error(opts, 'The output format does not accept multiple heading levels.')
#  opts.heading = opts.heading[:1]
db.write(out)

if opts.convert == 'html':
  out.write("\\end{document}\n")
out.close()

sys.exit(opts.errors)
