import os
import types

PROJECTS = {
	'tripedia.org': '/Users/Jan/Projekte/tripedia.org/tripedia',
	'oekosozialmarkt.com': '/Users/Jan/Projekte/oekosozialmarkt.com/oekosozialmarkt',
	'Mathics': '/Users/Jan/Projekte/Mathics/mathics',
	'Rindfleischfest': '/Users/Jan/Sites/rindfleischfest',
	'Exkursionsbauernhoefe': '/Users/Jan/Sites/bauern',
	'Auro Kubelka': '/Users/Jan/Sites/auro',
	'Stanzoptimierung': '/Users/Jan/Uni/Stanzoptimierung/src',
	'-BatchWorks': ['/Users/Jan/Projekte/BatchWorks/Src', '/Users/Jan/Projekte/BatchWorks/Components'],
	'-Mathador': '/Users/Jan/Projekte/Mathador',
	'-RLS-Info': '/Users/Jan/Projekte/RLS-Info',
	'-livelynet.net': '/Users/Jan/Projekte/livelynet.net/livelynet',
	'-Preisdetektiv': '/Users/Jan/Projekte/Preisvergleich/preisdetektiv',
}

EXCLUDE_DIRS = set(['_Kopien_', 'prototype', 'scriptaculous', 'innerdom', 'livepipe', 'gmapsutil', 'TBP', ])
EXCLUDE_FILES = set(['prototype.js', 'carousel.js', 'printf.js'])

TYPES = {
	'Pascal': 'pas',
	'C/C++': ['h', 'hpp', 'cpp', 'c'],
	'HTML': ['html', 'htm', 'xhtml', 'xhtm'],
	'CSS': 'css',
	'Python': 'py',
	'Java': 'java',
	'JavaScript': 'js',
	'PHP': 'php',
}

def flatten(seq):
	""" flattens lists and sequences to one dimension """

	if isinstance(seq, (list, types.GeneratorType)):
		for item in seq:
			for sub_item in flatten(item):
				yield sub_item
	else:
		yield seq

# inverse dictionary extension -> type name
TYPES_INV = dict(flatten(((ext, type) for ext in ([exts] if isinstance(exts, basestring) else exts)) for type, exts in TYPES.iteritems()))
    
def linecount(filename):
	""" determine the number of lines in a file """

	return sum(1 for line in open(filename, 'r'))
	
def inc_dict(d, k, i):
	""" increment the dictionary entry d[k] by i, or set it to i if not present already """

	try:
		d[k] += i
	except KeyError:
		d[k] = i
		
def project_key(p):
	""" sort key for a project name """
	
	if p.startswith('-'):
		return (1, p.lower())
	else:
		return (0, p.lower())
		
def html_table(table):
	html = ["<table>"]
	html.append("<thead><tr>" + "".join(("<th>%s</th>" % cell) for cell in table[0]) + "</tr></thead>")
	html.append("<tbody>")
	for row in table[1:]:
		html.append("<tr><th>%s</th>" % row[0] + "".join(("<td>%s</td>" % cell) for cell in row[1:]) + "</tr>")
	html.append("</tbody>")
	html.append("</table>")
	return "\n".join(html)
	
def text_table(table):
	row_widths = []
	for row in table:
		for index, cell in enumerate(row):
			if len(row_widths) <= index:
				row_widths += [0] * (index + 1 - len(row_widths))
			row_widths[index] = max(row_widths[index], len(unicode(cell)))
	text = []
	for row in table:
		text.append(' '.join((('%' + str(row_widths[index]) + 's') % cell) for index, cell in enumerate(row)))
	return "\n".join(text)

def main():
	result = {}
	for project, dirs in PROJECTS.iteritems():
		if isinstance(dirs, basestring):
			dirs = [dirs]
		lines = {}
		for dir in dirs:
			for dirpath, dirnames, filenames in os.walk(dir):
				for exclude in EXCLUDE_DIRS:
					try:
						dirnames.remove(exclude)
					except ValueError:
						pass
				for filename in filenames:
					if filename not in EXCLUDE_FILES:
						basename, ext = os.path.splitext(filename)
						ext = ext[1:]	# remove leading '.'
						type = TYPES_INV.get(ext)
						if type is not None:
							lc = linecount(os.path.join(dirpath, filename))
							inc_dict(lines, type, lc)
		result[project] = lines
	types_total = dict((type, sum(lines.get(type, 0) for project, lines in result.iteritems())) for type in TYPES)
	types = sorted(type for type, count in types_total.iteritems() if count > 0)
	
	"""html = ["<table>"]
	html.append("<thead><tr><th>Project</th>" + "".join(("<th>%s</th>" % type) for type in types) + "<th>Total</th></tr></thead>")
	html.append("<tbody>")
	for project, lines in sorted(result.iteritems(), key=lambda (p, l): project_key(p)):
		html.append("<tr><th>%s</th>" % project.lstrip('-') + "".join(("<td>%s</td>" % lines.get(type, "")) for type in types) + ("<td>%d</td>" % sum(lines.values())) + "</tr>")
	html.append("<tr><th>Total</th>" + "".join(("<td>%d</td>" % types_total[type]) for type in types) + ("<td>%d</td>" % sum(types_total.values())) + "</tr>")
	html.append("</tbody>")
	html.append("</table>")"""
	
	table = []
	table.append(["Project"] + types + ["Total"])
	for project, lines in sorted(result.iteritems(), key=lambda (p, l): project_key(p)):
		table.append([project.lstrip('-')] + [lines.get(type, "") for type in types] + [sum(lines.values())])
	table.append(["Total"] + [types_total[type] for type in types] + [sum(types_total.values())])
	#print '\n'.join(html)
	#print result
	
	print html_table(table)
	print text_table(table)
	
	#print table
	
if __name__ == '__main__':
	main()
