#
#  main.py
#  equation-formatter
#
#  Created by Nicholas Matsakis on 11/13/07.
#  Copyright __MyCompanyName__ 2007. All rights reserved.
#

#import modules required by application
import traceback
import objc
from Foundation import *
from AppKit import *
from PyObjCTools import AppHelper

def serviceSelector(fn):
    # this is the signature of service selectors
    return objc.selector(fn, signature="v@:@@o^@")

def ERROR(s):
    NSLog(u"ERROR: %s" % (s,))
    return s

def debug(s):
    #NSLog(s)
    return

class EquationFormatterService(NSObject):
    @objc.signature("v@:@@o^@")
    def doEquationFormatterService_userData_error_(self, pboard, data):
        try:
            debug(u"Fetching set of types")
            types = pboard.types()
        
            debug(u"Fetched set of types: %r" % (types,))
            if not(NSRTFPboardType in types):
                return NSLocalizedString(
                    "Error: Pasteboard doesn't contain RTF.",
                    "Pasteboard doesn't contain RTF.")
        
            
            # TODO: replace with the more generic "textTypes" based solution
            debug(u"Fetched RTF Data")
            rtfData = pboard.dataForType_(NSRTFPboardType)
            debug(u"Loaded rtfData %r" % (rtfData,))
            result = NSMutableAttributedString.alloc()
            result, docAttr = result.initWithRTF_documentAttributes_(rtfData)
            debug(u"Loaded attribute string")
        
            # First stage: replace any normal characters with their unicode
            # equivalents
            replacements = [
                (u"<->", u"\u2194"),
                (u"<-",  u"\u2190"),
                (u"->",  u"\u2192"),
                (u"<=>", u"\u21d4"),
                (u"<=",  u"\u21d2"),
                (u"=>",  u"\u21d2"),
                (u"|-",  u"\u21d2"),
                (u"\infty", u"\u221e"),
                (u"\times", u"\u2217"),
                (u"\ast", u"\u00D7"),
                (u"\cup", u"\u222a"),
                (u"\vee", u"\u2228"),
                (u"\notsubset", u"\u2284"),
                (u"\subseteq", u"\u2286"),
                (u"\subset", u"\u2282"),
                (u"\in", u"\u2208"),
                (u"\ni", u"\u220D"),
                (u"\notin", u"\u2209"),
                (u"\neg", u"\u00AC"),
                (u"\bot", u"\u22A5"),
                (u"\forall", u"\u2200"),
                (u"\exists", u"\u2203"),
                (u"\notexists", u"\u2204"),
                ]
            for orig, replacement in sorted(replacements,
                                            key=lambda (a,b): len(a),
                                            reverse=True):
                debug(u"Replacing %r with %r" % (orig, replacement))
                result.mutableString().replaceOccurrencesOfString_withString_options_range_(
                    orig, replacement, 0, NSRange(0, result.length()))
        
            # Second stage: Replace ^ and _ with super- and sub-scripts
            done = False
            while not done:
                result_str = result.string()
                for idx in reversed(range(0, result.length()-1)):
                    if result_str[idx] in ('^', '_'):
                        replace_range = raise_range = None
                        if result_str[idx+1] == '{':
                            close_idx = result_str.find('}', idx+2)
                            if close_idx != -1:
                                replace_range = NSRange(idx, close_idx-idx+1)
                                raise_range = NSRange(replace_range.location+2,
                                                      replace_range.length-3)
                        else:
                            replace_range = NSRange(idx, 2)
                            raise_range = NSRange(idx+1, 1)

                        if replace_range is not None:
                            assert raise_range is not None
                            raise_astr = NSMutableAttributedString.alloc().initWithAttributedString_(
                                result.attributedSubstringFromRange_(raise_range))
                            raise_astr.addAttribute_value_range_(
                                NSBaselineOffsetAttributeName, 
                    
        
            # Write back result to pasteboard
            debug(u"Writing attribute string back to PB")
            rtfData = result.RTFFromRange_documentAttributes_(
                NSRange(0, result.length()), docAttr)
            pboard.declareTypes_owner_([NSRTFPboardType], None)
            pboard.setData_forType_(rtfData, NSRTFPboardType)
            return None
        except:
            traceback.print_exc()
            return NSLocalizedString("ERROR: Python Error", "Python Error")                
    
def main():
    serviceProvider = EquationFormatterService.alloc().init()
    NSRegisterServicesProvider(serviceProvider, u'EquationFormatterService')
    AppHelper.runConsoleEventLoop()

if __name__ == '__main__':
    main()
