#!/usr/bin/env python
import os
import platform
import sys
import csv
import codecs
import datetime
from dateutil.parser import parse
import optparse

currencyvar = "$"

def myNewLine():
	if platform.system() == 'Windows':
		return "\r\n"
	else:
		return "\n"

def isnumeric(value):
	global currencyvar
	return str(value).replace(",","").replace(".", "").replace("-", "").replace(currencyvar, "").strip().isdigit()

def parseCSV(fn,debitheaders,accountheaders,notef,datef):
	notef = notef.strip()
	datef = datef.strip()
	f = open(fn, 'rb')
	reader = csv.DictReader(f)
	transaction = ""
	for item in reader:
		transaction = transaction + myNewLine() + ProcessEntry(item,debitheaders,accountheaders,notef,datef)
	f.close()
	return transaction

def checkDate(mstr):
	try:
	 	return parse(mstr).strftime('%Y/%m/%d').strip()
	except Exception as inst:
		return datetime.date.today().isoformat().replace('-','/').strip()

def ProcessEntry(item,dheader,accts,notef,datef):
	accounts = []
	accounts = accts[:]
	startline = ''
	dateline = ''
	noteline = ''
	if item.has_key(notef) and len(notef)>0:
		noteline = item[notef].strip()
	else:
		noteline = 'Transaction'
	
	if item.has_key(datef) and len(datef)>0:
		dateline = checkDate(item[datef].strip())
	else:
		currentdate = datetime.date.today().isoformat().replace('-','/').strip()
		dateline = currentdate
	
	startline = dateline + " * " + noteline
	count = 0
	for s in dheader:		
		if item.has_key(s.strip()) and isnumeric(item[s.strip()]) and len(accounts) > count:
			accounts[count] = accounts[count] + "\t\t" + item[s.strip()].strip()
		elif s[0] =='-' and item.has_key(s[1:].strip()) and isnumeric(item[s[1:].strip()]) and len(accounts) > count:
			accounts[count] = accounts[count] + "\t\t(" + item[s[1:].strip()].strip() + " * (-1))"
		count = count+1
	transaction = startline
	for s in accounts:
		transaction = transaction + myNewLine() + "\t" + s.strip()
	return transaction

def isCSV(myfile):
	if os.path.isfile(os.path.expanduser(myfile.strip())):
		return os.path.abspath(os.path.expanduser(myfile.strip()))
	else:
		print 'The file you specified does not exist'
		sys.exit()
		
def isReturnFile(myfile):
	if os.path.abspath(os.path.expanduser(myfile.strip())) != False:
		return os.path.abspath(os.path.expanduser(myfile.strip()))
	else:
		print 'You can\'t save to that location'
		sys.exit()


def SaveFile(transaction,myfile):
	mf = isReturnFile(myfile)
	if os.path.isfile(mf):
		fout = codecs.open(mf, "a", "utf-8")
		fout.write(unicode(myNewLine(), "utf-8"))
	else:
		fout = codecs.open(mf, "w", "utf-8")
	fout.write(unicode(transaction,"utf-8"))
	fout.close()
	print 'Saved File!'	
		
def main():
	global currencyvar
	didsomething = False
	
	desc = 'This tool allows you to convert CSVs into a format appropriate for Ledger.  It\'s particularly useful when you need to specify multipart transactions.'
	p = optparse.OptionParser(description=desc)
	utilities = optparse.OptionGroup(p, 'Utility Options')
	utilities.add_option('--open', '-o', dest="openfile", help="CSV file to open", default='', metavar='"<File Path>"')
	utilities.add_option('--save', '-s', dest="savefile", help="Save output to a file", default='', metavar='"<File Path>"')
	utilities.add_option('--currency', '-c', dest="currency", help="Currency character in data", default='', metavar='"$"')
	utilities.add_option('--date', '-d', dest="datefield", help="Name of field containing transaction date", default='', metavar='"date"')
	utilities.add_option('--note', '-n', dest="notefield", help="Name of field containing transaction note", default='', metavar='"note"')
	
	accountsec = optparse.OptionGroup(p, 'Account Options')
	accountsec.add_option('--accounts','-a',dest="accounts",help="Comma separated list of accounts",default='',metavar='"Assets:Checking, Equity:Revenue"')
	accountsec.add_option('--fields','-f',dest="fields",help="Comma separated list of field names (in the CSV) to include with accounts.  Fields prepended with a \"-\" will flip the sign of the field.",default='',metavar='"payment, tax"')
	
	p.add_option_group(utilities)
	p.add_option_group(accountsec)
	(options, arguments) = p.parse_args();
	
	if len(options.currency.strip())>0:
		currencyvar = options.currency.strip()
		
	if len(options.accounts.strip())>0:
		laccounts = options.accounts.strip().split(',')
	else:
		print 'No accounts specified'
		sys.exit()
	
	if len(options.fields.strip())>0:
		lfields = options.fields.strip().split(',')
	else:
		lfields = []
	
	if len(options.openfile.strip())>0:
		csvfile = isCSV(options.openfile.strip())
	else:
		print 'You must specify a file to open'
		sys.exit()
		
	transactions = parseCSV(csvfile,lfields,laccounts,options.notefield.strip(),options.datefield.strip()).strip()
	
	if len(options.savefile.strip())>0:
		SaveFile(transactions,options.savefile.strip())
		sys.exit()
	else:
		print unicode(transactions,"utf-8")
		sys.exit()
		
if __name__ == '__main__':
	main()