#
#  QIFImporter
#
#  Written by Niko Matsakis (c) 2006
#
#
# This code makes a couple of localization assumptions right now:
#
# 1. Assumes that the QIF is in UTF-8
# 2. Assumes that dates are stored dd.mm.yy
# 3. Assumes that amounts are stored 1,234.56

import objc, re
from Foundation import *
from AppKit import *

from PyObjCTools import NibClassBuilder
from QIFParser import QIFParser

NibClassBuilder.extractClasses("Drachma", bundle=NSBundle.mainBundle())

class QIFImporter(NibClassBuilder.AutoBaseClass):
    def init(self):
        self = super(QIFImporter, self).init()
        if self is None:
            return None
        # subclass specific initialization here
        # nib not loaded yet
        return self

    def awakeFromNib(self):
        self.drachma = self.drachmaController.drachma()
        self.mctx = self.drachma.managedObjectContext()
        self.mmodel = self.drachma.managedObjectModel()
    
    def importQIF_(self, sender):
        parser = QIFParser(self, 'utf-8')
        self.payee_cache = {}
        self.category_cache = {}
        for filenm in self.selectFileNames():
            try:
                fileobj = open(filenm)
                parser.parseQIF(fileobj)
            except IOError: pass
        self.payee_cache = None
        self.category_cache = None

    def selectFileNames(self):
        oPanel = NSOpenPanel.openPanel()
        oPanel.setAllowsMultipleSelection_(True)
        result = oPanel.runModalForDirectory_file_types_(
            NSHomeDirectory(), None, ['qif'])
        if result == NSOKButton:
            return oPanel.filenames()
        return []

    # Callbacks from QIFParser

    def payeeNamed(self, name):
        try:
            return self.payee_cache[name]
        except KeyError:
            pass
        res = self.drachma.payeeNamed_(name)
        self.payee_cache[name] = res
        return res

    def categoryNamed(self, name):
        try:
            return self.category_cache[name]
        except KeyError:
            pass
        res = self.drachma.categoryNamed_(name)
        self.category_cache[name] = res
        return res

    def handle_account(self, account):
        # for now, ignore this
        pass

    def handle_transaction(self, transaction):
        # Create a new expense.

        # Extract data from the transaction, using reasonable defaults:
        payeeName = transaction.get('payee', u'Not specified')
        memo = transaction.get('memo', u'')
        total = transaction.get('total', u'0.0')
        dateString = transaction.get('date', None)

        # Handle the date object, defaulting to a date in the distant past
        if dateString:
            dateObject = NSCalendarDate.dateWithString_calendarFormat_(
                dateString, u"%d.%m.%y")
        else:
            dateObject = NSDate.distantPast()

        # Create a list of categories and amounts for each category:
        categories = []
        if 'split' in transaction:
            for split in transaction['split']:
                splitcat = split.get('category', u'Uncategorized')
                splitamnt = split.get('amount', u'0.0')
                categories.append((splitcat, splitamnt))
        elif 'category' in transaction and transaction['category']:
            categories.append((transaction['category'], total))
        else:
            categories.append((u'Uncategorized', total))

        # Since we don't currently handle split transactions: create a
        # copy of the transaction for each category and amount.
        #
        # Note that we store EXPENSES, so a positive number for us
        # means money that was spent; QIF files store money spent as a
        # negative number, and therefore we must invert it.
        for catname, catamnt in categories:
            exp = NSEntityDescription.\
                  insertNewObjectForEntityForName_inManagedObjectContext_(
                "Expense", self.mctx)
            exp.setPayee_(self.payeeNamed(payeeName))
            exp.setMemo_(memo)
            exp.setCategory_(self.categoryNamed(catname))
            exp.setAmount_(-NSDecimalNumber.decimalNumberWithString_(
                catamnt.replace(",","")))
            exp.setDate_(dateObject)
            
        pass
