#!/usr/bin/python

from pyzotero import zotero
import ConfigParser, feedparser, json, optparse, os, re, shutil, sys, unicodedata

def ib64_patched(self, attrsD, contentparams):
    """Patch isBase64 to prevent Base64 encoding of JSON content"""
    return False

# Override feedparser's buggy isBase64 method until they fix it
feedparser._FeedParserMixin._isBase64 = ib64_patched

def backup_file(path):
    if (os.path.exists(path)):
        backupnum = 1
        backupfile = "%s~%d"%(path, backupnum)
        while (os.path.exists(backupfile)):
            backupnum = backupnum + 1
            backupfile = "%s~%d"%(path, backupnum)

        shutil.copy2(path, backupfile)

# turn unicode strings into ascii
clean_re = re.compile(u'[^A-Za-z]+')
def clean(s):
    # strip unicode accents
    s = unicode(s)
    s2 = ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
    return clean_re.sub('', s2)

# option parsing
usage = "usage: %prog [options] keymap"
parser = optparse.OptionParser(usage=usage)
parser.add_option("-u", "--userid", dest="userid", metavar="USERID")
parser.add_option("-k", "--key", dest="key", metavar="KEY")
(options, args) = parser.parse_args()

if len(args) == 0:
    parser.error("Please supply a keymap file!")

# set up existing keymap
keymapfile = os.path.abspath(args[0])
keymap = ConfigParser.SafeConfigParser()
keymap.optionxform = str
keymap.read(keymapfile)
if not(keymap.has_section('keymap')):
    keymap.add_section('keymap')
if not(keymap.has_section('meta')):
    keymap.add_section('meta')

if (not(os.path.exists(keymapfile)) and
    (options.userid is None or options.key is None)):
    parser.error("When creating a new keymap file, you must supply a USERID and KEY")

userid = options.userid or keymap.get('meta', 'userid')
apikey = options.key    or keymap.get('meta', 'key')
keymap.set('meta', 'userid', userid)
keymap.set('meta', 'key', apikey)

# keys we already know about, do not change the ezkey
known_keys = {}
for k, v in keymap.items('keymap'): 
    # use only the key itself
    zotkey = re.match(r"^([0-9A-Z_]+)", v).group(1)
    known_keys[zotkey] = k

zot = zotero.Zotero(userid, apikey)
    
collid = None
if keymap.has_option('meta', 'collectionid'):
    collid = keymap.get('meta', 'collectionid')
else:
    collections = zot.collections()
    collstr = "".join([ "%d. %s\n"%(i + 1, coll['name']) for i, coll in enumerate(collections) ])
    choice = raw_input("Which collection?\n\n%s> "%(collstr))
    collid =  collections[int(choice) - 1]['key']
keymap.set('meta', 'collectionid', collid)

start = 0

zot.add_parameters(start=0, limit=10)
items = zot.collection_items(collid)
while len(items) > 0:
    for item in items:
        key = item['key']
        if known_keys.has_key(key): continue

        date = "XXXX"
            
        if item.has_key('date'):
           date_key = 'date'
        elif item.has_key('dateEnacted'):
           date_key = 'dateEnacted'
        else:
           date_key = 'dateDecided'
        
        md = re.match(r'([0-9]{4})', item[date_key])
        if md is not None: date = md.group(1)

        if item.has_key('title'):
            title_key = 'title'
        elif item.has_key('nameOfAct'):
            title_key = 'nameOfAct'
        else:
            title_key = 'caseName'

        title = clean(item[title_key])

        creator = "Unknown"
        if item.has_key('creators') and len(item['creators']) > 0:
            creator = clean(item['creators'][0].get('lastName', 'Unknown'))

        ezkey = "%s%s"%(creator, date)
        # ensure we don't already have an ezkey CreatorDate
        if (keymap.has_option('keymap', ezkey)):
            extra = "a"
            while keymap.has_option('keymap', "%s%s"%(ezkey, extra)):
                extra = chr(ord(extra) + 1)
            ezkey = "%s%s"%(ezkey, extra)
        keymap.set('keymap', ezkey, "%s %s"%(key, title))
        known_keys[key] = ezkey

    start = start + len(items)
    zot.add_parameters(start=start, limit=10)
    items = zot.collection_items(collid)

backup_file(keymapfile)
keymap.write(open(keymapfile, 'w'))

if (len(args) > 1):
    ## write json file
    jsonfile = os.path.abspath(args[1])
    backup_file(jsonfile)

    items = {}
    for k, v in keymap.items('keymap'): 
        # use only the key itself
        zotkey = re.match(r"^([0-9A-Z_]+)", v).group(1)
        url = "https://api.zotero.org/users/%s/items/%s?key=%s&content=csljson"%(userid, zotkey, apikey)
        d = feedparser.parse(url)
        jsond = json.loads(d['entries'][0]['content'][0]['value'])
        ezkey = known_keys[jsond['id']]
        jsond['id'] = ezkey
        items[ezkey] = jsond
    fd = open(jsonfile, 'w')
    json.dump(items, fd, sort_keys=True, indent=4)
    fd.close()
