import sys
import tinycss

def sel_to_str(selector): return selector.as_css()
def dec_to_str(declaration): return declaration.value.as_css()

def get_rule_by_selector(selector, file2):
	selector = sel_to_str(selector)
	for rule in file2.rules:
		if selector == sel_to_str(rule.selector):
			return rule
	return None

def get_declaration_by_rule(declaration, rule2):
	declaration = declaration.name
	for decl in rule2.declarations:
		if declaration == decl.name:
			return decl
	return None

def main(file1, file2, outfile = None):
	p = tinycss.make_parser() # TODO: CSS3, invalid args, etc?
	file1 = p.parse_stylesheet_file(file1)
	file2 = p.parse_stylesheet_file(file2)

	file_1_declarations = {}

	diff = {}
	for rule in file1.rules:
		selectorstr = sel_to_str(rule.selector)
		file_1_declarations[selectorstr] = [d.name for d in rule.declarations]
		rule2 = get_rule_by_selector(rule.selector, file2)
		if None == rule2:
			# the rule/selector does not exists in file2
			diff[selectorstr] = dict([(d.name, (dec_to_str(d), False)) for d in rule.declarations ]), False
			continue

		for declaration in rule.declarations:
			declarationstr = dec_to_str(declaration)
			decl2 = get_declaration_by_rule(declaration, rule2)
			if None == decl2:
				# the declaration does not exists in file2
				if not selectorstr in diff:
					diff[selectorstr] = {}, False
				diff[selectorstr][0][declaration.name] = declarationstr, False
				continue

			if dec_to_str(declaration) != dec_to_str(decl2):
				# different value
				if not selectorstr in diff:
					diff[selectorstr] = {}, False
				diff[selectorstr][0][declaration.name] = declarationstr, True

	file_2_declarations = {}
	for rule in file2.rules:
		selstr = sel_to_str(rule.selector)
		file_2_declarations[selstr] = [d.name for d in rule.declarations if d.name not in file_1_declarations.get(selstr, [])]

	# make css file
	css = ''
	for selector, (declarations, r_exists) in diff.iteritems():
		_css = '%s {\n%%s}\n\n' % (selector.replace('%', '%%'))
		_css_items = ''
		for dec_name, (dec_value, d_exists) in declarations.iteritems():
			_css_items += '\t%s: %s%s;\n' % (dec_name, dec_value, ' !important /*overwriting claro.css*/' if d_exists else '')
		css += _css % _css_items

	css += '\n\n\n/* remove the following values from claro.css */\n\n'
	for selector, declarations in file_2_declarations.iteritems():
		if not declarations:
			continue
		_css = '%s {\n%%s\n}\n\n' % (selector.replace('%', '%%'))
		css += _css % '\n'.join(['\t%s: inherit !important;' % (dec_name,) for dec_name in declarations])

	if outfile:
		with open(outfile, 'w') as fd:
			fd.write(css)
	else:
		print css

	count_sel = len(file_1_declarations) + len(file_2_declarations)
	count_dec = sum([len(d) for d in file_1_declarations.values() + file_2_declarations.values()])
	print count_sel, count_dec

if __name__ == '__main__':
	if len(sys.argv) < 3 or any([h in sys.argv for h in ['-?', '-h', '--help']]):
		print 'CSS Diff: creates a CSS file which contains all changes between two css files'
		print 'usage:', sys.argv[0], '<claro.css>', '<umc.css>', '[<outfile>]'
		sys.exit(1)

	outfile = sys.argv[3] if len(sys.argv) > 3 else None
	main(sys.argv[1], sys.argv[2], outfile)
