#!/usr/bin/env python

"""Command-line tool to replace MathML with SVG throughout a document.

Replaces all instances of MathML throughout the document"""

import getopt, sys, os.path
from xml import sax
# from xml.sax.saxutils import XMLGenerator
from svgmath.tools.saxtools import XMLGenerator, ContentFilter
from svgmath.mathhandler import MathHandler, MathNS

#CONFIGDIR=os.path.dirname(__file__)
CONFIGDIR="/etc/SVGMath/"

def open_or_die(fname, fmode, role):        
    try: return open(fname, fmode)
    except IOError, xcpt: 
        print "Cannot open %s file '%s': %s" % (role, fname, str(xcpt))
        sys.exit(1)

def usage():
    sys.stderr.write("""
Usage: math2svg.py [options] FILE
Replaces MathML formulae in a document by SVG images. Argument is a file name.

Options:
    -h, --help               display this synopsis and exit
    -s, --standalone         treat input as a standalone MathML document
    -o FILE, --output=FILE   write results to FILE instead of stdout
    -c FILE, --config=FILE   read configuration from FILE
    -e ENC,  --encoding=ENC  produce output in ENC encoding
""")  

class MathFilter (ContentFilter):
    def __init__(self, out, mathout):
        ContentFilter.__init__(self, out)
        self.plainOutput = out
        self.mathOutput = mathout
        self.depth = 0

    # ContentHandler methods
    def setDocumentLocator(self, locator):
        self.plainOutput.setDocumentLocator(locator)
        self.mathOutput.setDocumentLocator(locator)

    def startElementNS(self, elementName, qName, attrs):
        if self.depth == 0:
            (namespace, localName) = elementName
            if namespace == MathNS:
                self.output = self.mathOutput
                self.depth = 1
        else: self.depth += 1
        ContentFilter.startElementNS(self, elementName, qName, attrs)

    def endElementNS(self, elementName, qName):
        ContentFilter.endElementNS(self, elementName, qName)
        if self.depth > 0:
            self.depth -= 1
            if self.depth == 0:
                self.output = self.plainOutput

def main():
    try:
        (opts, args) = getopt.getopt(sys.argv[1:], "c:e:ho:s", ["config=", "encoding=", "help", "output=", "standalone"])
    except getopt.GetoptError:
        usage(); sys.exit(2)
    
    outputfile = None
    configfile = None
    encoding = 'utf-8'
    standalone = False
  
    for o, a in opts:
        if o in ("-h", "--help"):       usage(); sys.exit(0)
        if o in ("-o", "--output"):     outputfile = a
        if o in ("-c", "--config"):     configfile = a
        if o in ("-e", "--encoding"):   encoding = a
        if o in ("-s", "--standalone"): standalone = True
     
    # Check input
    if len(args) < 1:
        sys.stderr.write ("No input file specified!\n")
        usage(); sys.exit(1)        
    elif len(args) > 1: 
        sys.stderr.write("WARNING: extra command line arguments ignored\n")

    source = open_or_die(args[0], "rb", "input") 
        
    # Determine output destination
    if outputfile is None: 
        output = sys.stdout 
    else: 
        output = open_or_die(outputfile, "wb", "output") 
  
    # Determine config file location
    if configfile is None:
        configfile = os.path.join(CONFIGDIR, "svgmath.xml")
    config = open_or_die(configfile, "rb", "configuration")    

    # Create the converter as a content handler. 
    saxoutput = XMLGenerator(output, encoding)
    handler = MathHandler(saxoutput, config)
    if not standalone:
        handler = MathFilter(saxoutput, handler)
    
    # Parse input file
    exitcode = 0
    try:
        parser = sax.make_parser()
        parser.setFeature(sax.handler.feature_namespaces, 1)
        parser.setContentHandler(handler)
        parser.parse(source)
    except sax.SAXException, xcpt:
        print "Error parsing input file %s: %s" % (args[0], xcpt.getMessage())
        exitcode = 1
    source.close()
    if outputfile is not None:
        output.close()
    sys.exit(exitcode)
    
if __name__ == "__main__":
    main()
