import pkg_resources
import re

from genshi.builder import tag

from trac.core import Component, implements
from trac.config import Option
from trac.wiki.formatter import format_to_oneliner
from trac.util.datefmt import to_timestamp, to_datetime
from trac.mimeview.api import Context

# Interfaces
from trac.timeline.api import ITimelineEventProvider
from trac.web import IRequestHandler
from trac.web.chrome import INavigationContributor, ITemplateProvider

from api import BuildBotSystem

class TracBuildBotWatcher(Component):
	implements(ITimelineEventProvider, IRequestHandler, ITemplateProvider,
		INavigationContributor)
	buildbot_url = Option('bbwatcher', 'buildmaster', '127.0.0.1:8010',
		'The location of the BuildBot webserver. Do not include the /xmlrpc')

	BUILDER_REGEX = r'/buildbot/builder(?:/(.+))?$'
	BUILDER_RE = re.compile(BUILDER_REGEX)
	# Template Provider
	def get_htdocs_dirs(self):
		return []
	def get_templates_dirs(self):
		return [pkg_resources.resource_filename('bbwatcher', 'templates')]

	# Nav Contributor
	def get_active_navigation_item(self, req):
		return 'buildbot'
	def get_navigation_items(self, req):
		yield 'mainnav', 'buildbot', tag.a('BuildBot',href=req.href.buildbot())

	# Timeline Methods
	def get_timeline_filters(self, req):
		yield  ('bbwatcher', 'Builds', False)

	def get_timeline_events(self, req, start, stop, filters):
		#if not 'bbwatcher' in filters:
		#	return
		try:
			master = BuildBotSystem(self.buildbot_url)
		except Exception, e:
			print 'Error hitting BuildBot', e
			return
		# This was a comprehension: the loop is clearer
		for build in master.getAllBuildsInInterval(to_timestamp(start), to_timestamp(stop)):
			# BuildBot builds are reported as
			# (builder_name, num, end, branch, rev, results, text)
			print 'Reporting build', build
			yield ('build', to_datetime(build[2]), '', build)

	def render_timeline_event(self, context, field, event):
		builder_name, num, end, branch, rev, results, text = event[3]
		if field == 'url':
			return None
		elif field == 'title':
			return tag('Build ', tag.a('#%s'%num, href=context.href.buildbot('builder/%s/%s'%(builder_name, num))),
				' of ', builder_name, ' ', results == 'success' and tag.span('passed', style="color: #080") or tag.span('failed', style="color: #f00"))
		elif field == 'description':
			return format_to_oneliner(self.env, context, 'Built from %s'%(rev and 'r%s sources'%rev or 'local changes (see TryBuildUsage)'))

	# RequestHandler
	def _handle_builder(self, req):
		m = self.BUILDER_RE.match(req.path_info)
		try:
			builder = m.group(1) or None
		except Exception, e:
			builder = None
		master = BuildBotSystem(self.buildbot_url)
		if builder is None:
			data = { 'names': master.getAllBuilders() }
			return 'bbw_allbuilders.html', data, 'text/html'
		else:
			class Foo:
				pass
			b = Foo()
			b.name = str(builder)
			b.current = 'CURRENT-TEXT'
			b.recent = []
			b.slaves = []
			data = { 'builder': b }
			try:
				master = BuildBotSystem(self.buildbot_url)
				data = { 'builder': master.getBuilder(builder) }
			except Exception, e:
				print 'Error fetching builder stats', e
			data['context'] = Context.from_request(req, ('buildbot', builder))
			return 'bbw_builder.html', data, 'text/html'

	def match_request(self, req):
		return req.path_info.startswith('/buildbot') and 1 or 0

	def process_request(self, req):
		if req.path_info.startswith('/buildbot/builder'):
			return self._handle_builder(req)
		return 'bbw_welcome.html', { 'url': self.buildbot_url }, 'text/html'
