import os, re, string, sys
import frontend, reason_qualifier

color_map = {
	'header'        : '#e5e5c0', # greyish yellow
	'blank'         : '#ffffff', # white
	'plain_text'    : '#e5e5c0', # greyish yellow
	'borders'       : '#bbbbbb', # grey
	'white'		: '#ffffff', # white
	'green'		: '#66ff66', # green
	'yellow'	: '#fffc00', # yellow
	'red'		: '#ff6666', # red

	#### additional keys for shaded color of a box 
	#### depending on stats of GOOD/FAIL
	'100pct'  : '#80ff80', # green, 94% to 100% of success
	'95pct'   : '#c0ff80', # step twrds yellow, 88% to 94% of success
	'90pct'   : '#ffff80', # yellow, 82% to 88%
	'85pct'   : '#ffc040', # 76% to 82%
	'75pct'   : '#ff4040', # red, 1% to 76%
	'0pct'    : '#d080d0', # violet, <1% of success	

}


def color_keys_row():
	""" Returns one row table with samples of 'NNpct' colors
		defined in the color_map
		and numbers of corresponding %%
	"""
	### This function does not require maintenance in case of	
	### color_map augmenting - as long as 
	### color keys for box shading have names that end with 'pct'
	keys = filter(lambda key: key.endswith('pct'), color_map.keys())
	def num_pct(key):
		return int(key.replace('pct',''))
	keys.sort(key=num_pct)
	html = ''
	for key in keys:
		html+= "\t\t\t<td bgcolor =%s>&nbsp;&nbsp;&nbsp;</td>\n"\
				% color_map[key]
		hint = key.replace('pct',' %')
		if hint[0]<>'0': ## anything but 0 %
			hint = 'to ' + hint
		html+= "\t\t\t<td> %s </td>\n" % hint

	html = """
<table width = "500" border="0" cellpadding="2" cellspacing="2">\n
	<tbody>\n
		<tr>\n
%s
		</tr>\n
	</tbody>
</table><br>
""" % html
	return html

def hover_html(link, href, hover_text):
	""" Returns the snippet of html for generating the hover over links.
	"""
	return '<center><a class="info" href="%s">%s<span>%s</span></a></center>' % \
		(link, href, hover_text)

class box:
	def __init__(self, data, color_key = None, header = False, link = None,
		     tooltip = None, row_label = None, column_label = None):
		if data:
			data = "<tt>%s</tt>" % data
		if link and tooltip:
			self.data = hover_html(link, data, '%s:%s<br>%s' % 
						(row_label, column_label, tooltip))
		elif tooltip:
			self.data = hover_html('#', data, tooltip)
		elif link:
			self.data = '<a href="%s">%s</a>' % (link, data)
		else:
			self.data = hover_html('about:blank',
				'&nbsp;&nbsp;&nbsp;', '%s:%s' % (row_label, column_label))

		if color_map.has_key(color_key):
			self.color = color_map[color_key]
		elif header:
			self.color = color_map['header']
		elif data:
			self.color = color_map['plain_text']
		else:
			self.color = color_map['blank']
		self.header = header


	def html(self):
		if self.data:
			data = self.data
		else:
			data = '&nbsp'

		if self.header:
			box_html = 'th'
		else:
			box_html = 'td'

		return "<%s bgcolor=%s>%s</%s>" % \
					(box_html, self.color, data, box_html)


def grade_from_status(status):
	# % of goodness
	# GOOD (6)  -> 1
	# TEST_NA (8) is not counted
	# ##  If the test doesn't PASS, it FAILS
	# else -> 0

	if status == 6:
		return 1.0
	else:
		return 0.0


def average_grade_from_status_count(status_count):
	average_grade = 0
	total_count = 0
	for key in status_count.keys():
		if key != 8: # TEST_NA status
			average_grade += (grade_from_status(key)
						* status_count[key])
			total_count += status_count[key]
	if total_count != 0:
		average_grade = average_grade / total_count
	else:
		average_grade = 0.0
	return average_grade


def shade_from_status_count(status_count):
	if not status_count:
		return None
	
	## average_grade defines a shade of the box
	## 0 -> violet
	## 0.76 -> red
	## 0.88-> yellow
	## 1.0 -> green	
	average_grade = average_grade_from_status_count(status_count)
	
	## find appropiate keyword from color_map
	if average_grade<0.01:
		shade = '0pct'
	elif average_grade<0.75:
		shade = '75pct'
	elif average_grade<0.85:
		shade = '85pct'
	elif average_grade<0.90:
		shade = '90pct'
	elif average_grade<0.95:
		shade = '95pct'
	else:
		shade = '100pct'
		
	return shade


def status_html(db, box_data, shade):
	"""
	status_count: dict mapping from status (integer key) to count
	eg. { 'GOOD' : 4, 'FAIL' : 1 }
	"""
	status_count = box_data.status_count
	if 6 in status_count.keys():
		html = "%d&nbsp;/&nbsp;%d " \
			%(status_count[6],sum(status_count.values()))
	else:
		html = "%d&nbsp;/&nbsp;%d " % \
			(0, sum(status_count.values()))

	if box_data.reasons_list:
		reasons_list = box_data.reasons_list
		aggregated_reasons_list = \
			reason_qualifier.aggregate_reason_fields(reasons_list)
		for reason in aggregated_reasons_list:
			## a bit of more postprocessing
			## to look nicer in a cell
			## in future: to do subtable within the cell
			reason = reason.replace('<br>','\n')
			reason = reason.replace('<','[').replace('>',']')
			reason = reason.replace('|','\n').replace('&',' AND ')
			reason = reason.replace('\n','<br>')
			html += '<br>' + reason

	tooltip = ""
	for status in sorted(status_count.keys(), reverse = True):
		status_word = db.status_word[status]
		tooltip += "%d %s " % (status_count[status], status_word)
	return (html,tooltip)


def status_count_box(db, tests, link = None):
	"""
	Display a ratio of total number of GOOD tests
	to total number of all tests in the group of tests.
	More info (e.g. 10 GOOD, 2 WARN, 3 FAIL) is in tooltips
	"""
	if not tests:
		return box(None, None)

	status_count = {}
	for test in tests:
		count = status_count.get(test.status_num, 0)
		status_count[test.status_num] = count + 1
	return status_precounted_box(db, status_count, link)


def status_precounted_box(db, box_data, link = None,
				 x_label = None, y_label = None):
	"""
	Display a ratio of total number of GOOD tests
	to total number of all tests in the group of tests.
	More info (e.g. 10 GOOD, 2 WARN, 3 FAIL) is in tooltips
	"""
	status_count = box_data.status_count
	if not status_count:
		return box(None, None)
	
	shade = shade_from_status_count(status_count)	
	html,tooltip = status_html(db, box_data, shade)
	precounted_box = box(html, shade, False, link, tooltip,
				x_label, y_label)
	return precounted_box


def print_table(matrix):
	"""
	matrix: list of lists of boxes, giving a matrix of data
	Each of the inner lists is a row, not a column.

	Display the given matrix of data as a table.
	"""

	print ('<table bgcolor="%s" cellspacing="1" cellpadding="5" '
	       'style="margin-right: 200px;">') % (
	       color_map['borders'])
	for row in matrix:
		print '<tr>'
		for element in row:
			print element.html()
		print '</tr>'
	print '</table>'


def sort_tests(tests):
	kernel_order = ['patch', 'config', 'build', 'mkinitrd', 'install']

	results = []
	for kernel_op in kernel_order:
		test = 'kernel.' + kernel_op
		if tests.count(test):
			results.append(test)
			tests.remove(test)
	if tests.count('boot'):
		results.append('boot')
		tests.remove('boot')
	return results + sorted(tests)


def print_main_header():
	hover_css="""\
a.info{
    position:relative; /*this is the key*/
    z-index:1
    color:#000;
    text-decoration:none}

a.info:hover{z-index:25;}

a.info span{display: none}

a.info:hover span{ /*the span will display just on :hover state*/
    display:block;
    position:absolute;
    top:1em; left:1em;
    min-width: 100px;
    overflow: visible;
    border:1px solid #036;
    background-color:#fff; color:#000;
    text-align: left
}
"""
	print '<head><style type="text/css">'
	print 'a { text-decoration: none }'
	print hover_css
	print '</style></head>'
	print '<h2>'
	print '<a href="compose_query.cgi">Functional</a>'
	print '&nbsp&nbsp&nbsp'
	print '<a href="machine_benchmark.cgi">Performance</a>'
	print '&nbsp&nbsp&nbsp'
	print '<a href="http://test.kernel.org/autotest">[about Autotest]</a>'
	print '</h2><p>'


def group_name(group):
	name = re.sub('_', '<br>', group.name)
	if re.search('/', name):
		(owner, machine) = name.split('/', 1)
		name = owner + '<br>' + machine
	return name
