#!/usr/bin/env python
# Copyright (c) 2009-2010, Michael Gorven, Stefano Rivera
# Released under terms of the MIT/X/Expat Licence. See COPYING for details.

import gzip
from optparse import OptionParser
from os.path import basename, exists
import re
from sys import exit, stderr, path

path.insert(0, '.')

import ibid
from ibid.compat import json
from ibid.config import FileConfig
from ibid.plugins.factoid import Factoid, FactoidName, FactoidValue, Factpack, \
                                 escape_name

parser = OptionParser(usage=u"""%prog <factpack>
factpack is a JSON-formatted set of factoids (possibly gzipped)""")
parser.add_option('-r', '--remove', action='store_true', help='Remove the named factpack from the database')
parser.add_option('-f', '--force', action='store_true', help='Remove factoids which have been modified')
parser.add_option('-s', '--skip', action='store_true', help='Skip factoids which already exist in the database')
options, args = parser.parse_args()

if len(args) != 1:
    parser.error(u'No factpack specified')

filename = unicode(args[0])

ibid.config = FileConfig("ibid.ini")
ibid.config.merge(FileConfig("local.ini"))
ibid.reload_reloader()
ibid.reloader.reload_databases()
session = ibid.databases.ibid()

if options.remove:
    factpack = session.query(Factpack).filter_by(name=filename).first()
    if not factpack:
        print >> stderr, u'Factpack not loaded'
        exit(3)

    extras = []
    for factoid in session.query(Factoid).filter_by(factpack=factpack.id).all():
        for part in factoid.names + factoid.values:
            if part.factpack or options.force:
                session.delete(part)
            else:
                extras.append(hasattr(part, 'name') and part.name or part.value)
        session.delete(factoid)

    if extras and not options.force:
        print >> stderr, u'The following factoid entries have been added. ' \
                         u'Use -f to force removal.'
        for extra in extras:
            print extra
        exit(6)

    session.delete(factpack)
    session.commit()
    session.close()

    print u"Factpack removed"
    exit(0)

if not exists(filename):
    print >> stderr, u"File doesn't exist"
    exit(3)

if filename.endswith('.gz'):
    f = gzip.GzipFile(filename, 'r')
else:
    f = file(filename, 'r')
try:
    facts = json.loads(f.read())
except ValueError, e:
    print >> stderr, u"Invalid factpack"
    exit(4)
f.close()

name = unicode(re.sub(r'\.json(?:\.gz)?$', '', basename(filename)))
factpack = session.query(Factpack).filter_by(name=name).first()
if factpack:
    print >> stderr, u'Factpack is already imported'
    exit(5)

factpack = Factpack(name)
session.save(factpack)
session.flush()

existing = []
for names, values in facts:
    factoid = Factoid(factpack.id)
    for name in names:
        name = unicode(name)
        if session.query(FactoidName).filter_by(name=escape_name(name)).first():
            existing.append(name)
            continue
        fname = FactoidName(name, None, factpack=factpack.id)
        factoid.names.append(fname)
    for value in values:
        fvalue = FactoidValue(unicode(value), None, factpack=factpack.id)
        factoid.values.append(fvalue)
    if len(factoid.names) > 0:
        session.save(factoid)

if existing and not options.skip:
    print >> stderr, u'The following factoids already exist in the database. ' \
                     u'Please remove them before importing this factpack, ' \
                     u'or use -s to skip them'
    for name in existing:
        print >> stderr, name
    session.rollback()
    exit(6)

session.commit()
session.close()
print "Factpack imported"

# vi: set et sta sw=4 ts=4:
