import re, sys, datetime

# Example:
# #KONTO 2941 "Upplupna sociala avgifter"
# #KTYP 2941 S
# #SRU 2941 305

dateStandard = 1

def convert_date(s):
	if len(s)==10:
		return int(s[0:4]+s[5:7]+s[8:10])
	if len(s)<8:
		return 0
	return int(s)

def xmlSafe(s):
	c = s.replace('&','&amp;')
	c = c.replace('<','&lt;')
	c = c.replace('>','&gt;')
	return c

f = sys.stdin
s = f.read()
f.close()
s = s.split('\r') # Allows also for MAC format.
s = [i.strip() for i in s]

codecs = {"PC8":"cp437", "UTF":"utf_8", "UTF8":"utf_8", "UTF-8":"utf_8", "MAC":"mac_roman"}

format = re.compile('^#FORMAT\s+(\w+)', re.MULTILINE)
konto = re.compile('#KONTO\s+"?((?<=")[^"]+|\d+?)"?\s+"?((?<=")[^"]*|.*?)"?\s*$', re.MULTILINE)
orgnr = re.compile('#ORGNR\s+"?(\d{6,6}-\d{4,4})"?', re.MULTILINE)
valuta = re.compile('#VALUTA\s+(\w+)', re.MULTILINE)
prog = re.compile('#PROGRAM\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?', re.MULTILINE)
ktyp = re.compile('^#KTYP\s+(\d+)\s+"?((?<=")[^"]*|\S*)"?', re.MULTILINE)
sru =  re.compile('^#SRU\s+(\d+)\s+([BRU]?\d+)', re.MULTILINE)
momskod = re.compile('^#MOMSKOD\s+(\d+)\s+(\w+)', re.MULTILINE)
rar = re.compile('^#RAR\s+"?((?<=")[^"]*|.*?)"?\s+([0123456789-]+)\s+([0123456789-]+)', re.MULTILINE)
dim = re.compile('^#DIM\s+(\d+)\s+"?((?<=")[^"]*|\S*)"?', re.MULTILINE)
ib = re.compile('^#IB\s+"?((?<=")[^"]*|.*?)"?\s+(\d+)\s+([0123456789.-]+)', re.MULTILINE)
objekt = re.compile('^#OBJEKT\s+(\d+)\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?', re.MULTILINE)
#ver = re.compile('^#VER "?([^"]+?)"? (\d+) ([0123456789-]+) "?([^"]*?)"? [^{]*?(.*?)\n}\n', re.MULTILINE | re.DOTALL)
ver = re.compile('^#VER\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?\s+"?([0123456789-]+)"?\s+"?((?<=")[^"]*|\S*)"?\s+"?([0123456789-]*)"?(.*?)\n}', re.MULTILINE | re.DOTALL)
trans = re.compile('#([RB]*)TRANS\s+"?((?<=")[^"]+|\d+?)"?\s+{([^}]*)}\s+([0123456789.-]+)(.*)', re.MULTILINE)
rbtrans_part2 = re.compile('\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?\s+"?((?<=")[^"]*|\S*)"?')
kst = re.compile('"?((?<=")[^"]+|\d+)"?\s+"?((?<=")[^"]+|\d+)"?')
kontoplansTyper = (' ','T','S','I','K','K','K','K','K','K')

a = '\n'.join(s)
# Note that KP files are usually ISO-8859-1, while SE files are CP437. This might be indicated by '^#FORMAT PC8'
# The standard says PC8 (which is extended 8-bit ASCII).
m = format.findall(a)
if (len(m) > 0):
	if (codecs.has_key(m[0])):
		a = a.decode(codecs[m[0]]).encode('utf_8')
else:
	a = a.decode(codecs["PC8"]).encode('utf_8') # Default ?
	
m = prog.findall(a)
if (len(m) > 0):
	if (m[0][0]=='XOR Compact' and m[0][1]=='4.5251B'):
		dateStandard = 0
		
kontoplan = {}
verifikationer = []
obj = {}

#
# Fiscal years
fiscal_years = {}
m = rar.findall(a)
# print m
for i in m:
	d2 = convert_date(i[2])
	if (d2 % 100) == 1:
		# First day of the month.
		yearnum = d2 / 10000
		monthnum = (d2 / 100) % 100
		day = d2 % 100
		if monthnum in [2,4,6,8,9,11]:
			monthnum = monthnum - 1
			day = 31
		elif monthnum == 1:
			yearnum = yearnum - 1
			monthnum = 12;
			day = 31;
		elif monthnum in [5, 7, 10, 12]:
			monthnum = monthnum - 1
			day = 30
		else:
			monthnum = 2
			if ((yearnum % 4) == 0) and yearnum != 2000:
				day = 29
			else:
				day = 28
		d2 = yearnum * 10000 + monthnum * 100 + day		
    
	fiscal_years[i[0]] = [convert_date(i[1]), d2, []]
    
# print fiscal_years

#
# IB
m = ib.findall(a)
for i in m:
	if fiscal_years.has_key(i[0]):
		fiscal_years[i[0]][2].append(i[1:3])

#
# Objekt / kostnadsstallen
d = dim.findall(a)
for i in d:
	nummer = i[0]
	obj[nummer] = {'nummer':nummer, 'namn':i[1], 'delar':[]}
m = objekt.findall(a)
for i in m:
	nummmer = i[0]
	try:
		obj[nummer]['delar'].append({'nummer':i[1], 'namn':xmlSafe(i[2])})
	except:
		pass

# Verifikationer
m = ver.findall(a)
lacking_number_index = 0
for i in m:
	nummer = i[1]
	#sys.stderr.write(str(nummer) + '\n')
	verifikation = {'serie':i[0], 'datum':convert_date(i[2]), 'text':xmlSafe(i[3]), 'nummer':nummer, 'regdatum':convert_date(i[4])}
	n = trans.findall(i[5])
	verifikation['transaktioner'] = []
	skip = None
	for j in n:
		if skip != None:
			if skip[1:4] == j[1:4]:
				skip = None
				continue
			skip = None
		x = {'konto':j[1], 'belopp':j[3]}
		k = kst.search(j[2])
		if k:
			x['objekt'] = k.group(1)
			x['objektnummer'] = k.group(2)
		if j[0] != '':
			x['status'] = j[0].lower();
			part2 = rbtrans_part2.match(j[4])
			if part2 == None:
				x['when'] = verifikation["datum"]
				x['who'] = "?"
			else:
				j2 = part2.groups()
				x['when'] = convert_date(j2[0]);
				x['who'] = j2[3];
			if j[0] == 'R': skip = j
		verifikation['transaktioner'].append(x)
		
	if verifikation['nummer'] == '': 
		verifikation['nummer']=str(2147383647 + lacking_number_index)
		lacking_number_index += 1
		
	verifikationer.append(verifikation)
		
	
#
# Konton
m = konto.findall(a)
for i in m:
	kontoplan[i[0]] = {'namn':i[1]}
	
#
# Kontotyper
m = ktyp.findall(a)
for i in m:
	try:
		kontoplan[i[0]]['typ'] = i[1]
	except:
		pass

#
# SRU
m = sru.findall(a)
for i in m:
	try:
		kontoplan[i[0]]['sru'] = i[1]
	except:
		pass
for k in kontoplan.keys():
	kontoplan[k].setdefault('sru', '')

m = momskod.findall(a)
for i in m:
	try:
		kontoplan[i[0]]['moms'] = i[1]
	except:
		pass

for k in kontoplan.keys():
	kontoplan[k].setdefault('moms','')
# 	print int(k)/1000, kontoplan[k]['typ']
	ktypIndex = int(k)/1000;
	if ktypIndex >= len(kontoplansTyper):
		ktypIndex = len(kontoplansTyper) - 1;
	kontoplan[k].setdefault('typ',kontoplansTyper[ktypIndex])
	kontoplan[k]['namn'] = xmlSafe(kontoplan[k]['namn'])
		
# Strings with ampersands must be htmlentified (even within quotes!).

print """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>"""

# print '<key>totalItemsToImport</key><integer>%d</integer>' % (len(kontoplan)+len(obj)+len(fiscal_years)+len(verifikationer))

# Print konton
print '<key>konton</key><array>'
xml = ['<dict><key>nummer</key><integer>%d</integer><key>namn</key><string>%s</string><key>typ</key><string>%s</string><key>sru</key><string>%s</string><key>moms</key><string>%s</string></dict>' % (int(k)*100000, kontoplan[k]['namn'], kontoplan[k]['typ'], kontoplan[k]['sru'], kontoplan[k]['moms']) for k in kontoplan.keys()]
for x in xml:
	print x
print '</array>'

# Print objekt
print '<key>objekt</key><array>'	
for x in obj.keys():
	print '<dict>'
	print '<key>nummer</key><integer>%d</integer><key>namn</key><string>%s</string>' % (int(obj[x]['nummer']), obj[x]['namn'])
	print '<key>delar</key><array>'
	j = 1000;
	for i in obj[x]['delar']:
		try:
			objnr = int(i["nummer"])
		except ValueError:
			objnr = j
		j = j + 1	
		print '<dict><key>nummer</key><integer>%d</integer><key>namn</key><string>%s</string></dict>' % (objnr, i['namn'])
	print '</array></dict>'

print '</array>'

# Print orgnr
m = orgnr.findall(a)
if len(m) > 0:
	print '<key>orgnr</key><string>%s</string>' % (m[0],)

# Valutakod
m = valuta.findall(a)
if len(m) > 0:
    valutakod = m[0].upper()
else:
    valutakod = 'SEK'
print '<key>valuta</key><string>%s</string>' % (valutakod,)

# Print fiscal years
print '<key>fiscalYears</key><array>'
for x in fiscal_years.keys():
	print '<dict>'
	print '<key>nummer</key><integer>%d</integer><key>start</key><integer>%s</integer><key>stop</key><integer>%s</integer>' % (int(x), fiscal_years[x][0], fiscal_years[x][1])
	print '</dict>'
print '</array>'

print '<key>ib</key><array>'
for x in fiscal_years.keys():
	# Print saldon.
	for y in fiscal_years[x][2]:
		print '<dict><key>year</key><integer>%d</integer><key>nummer</key><integer>%d</integer><key>saldo</key><real>%f</real></dict>'% (int(x),int(y[0])*100000, float(y[1]))
print '</array>'
		
# Print verifikationer.
print '<key>verifikationer</key><array>'
for x in verifikationer:
	print '<dict><key>nummer</key><integer>%d</integer><key>serie</key><string>%s</string>' % (int(x['nummer']), x['serie'])
	print '<key>namn</key><string>%s</string><key>datum</key><integer>%s</integer>' % ( x['text'], x['datum'])
	if x['regdatum'] != 0:
		print "<key>regdatum</key><integer>%s</integer>" % (x['regdatum'],)
	print '<key>transaktioner</key><array>'
	for y in x['transaktioner']:
		print '<dict>'
		print '<key>konto</key><integer>%d</integer><key>belopp</key><string>%s</string>' % (int(y['konto'])*100000, y['belopp'])
		if y.has_key('objekt'):
			try:
				objektnummer = int(y['objektnummer'])
				print '<key>objektnummer</key><integer>%d</integer><key>objekt</key><string>%s</string>' % (objektnummer, y['objekt'])
			except ValueError:
				pass
		if y.has_key('status'):
			print '<key>who</key><string>%s</string><key>when</key><integer>%s</integer><key>status</key><string>%s</string>' % (y['who'],y['when'],y['status'])
		print '</dict>'
	print '</array></dict>'
	
print '</array>'

print '</dict></plist>'
sys.exit(0)
