from django import template
from django.conf import settings
from django.utils.translation import ugettext as _

class SimpleMenu(object):
	"""
	Stores a tree-like menu hierarchy, and renders it up to a chosen item
	on request.
	"""
	def __init__(self, menulist):
		"""
		Initializes the class.
		
		The menulist argument is a dictionary of menus. Each key is the menu
		label; the corresponding value is a list of (item_label, urlname)
		pairs.  The 'urlname' is then looked up in the URL configuration in
		order to correctly render the matching link. (See example below.)
		"""
		self.menus = menulist

	def render(self, menu_name, depth=0, active=None):
		"""
		The render() method returns a HTML string suitable for use as a
		menu bar on a given page.
		
		menu_name: the label of a menu, as specified at class initialization.
		
		depth (kw): an integer specifying how far into the tree this is being
		rendered.  Usually the render() method takes care of the whole menu,
		but it may be occasionally useful to delegate a single sub-menu to the
		SimpleMenu class.  Note that this parameter only affects the CSS class.
		
		active(kw): the active label, if any, in the menu.
		"""
		from django.core.urlresolvers import reverse
		s = '<div class="menu depth%d"><ul>' % depth
		for label, view in self.menus[menu_name]:
			s += '<li class="%s"><a href="%s">%s</a></li>' % (['nonactive',
				'active'][view==active], reverse(view), label)
		return s + '</ul></div>'

menu = SimpleMenu(settings.MENUITEMS)

# Example:
# MENUITEMS = {
#	'root': ((_('Venues'), 'venue_menu'), (_('My account'), 'account_menu')),
#	'venue_menu': ((_('Browse'), 'venue_browse'), (_('New venue'), 'eatout-add-venue'),)
#}



class MenuNode(template.Node):
	"""
	The menu tag takes a menu path whose components are labels separated by spaces.
	All the components from the first to the next-to-last are menu labels, and
	they are going to be rendered as menu bars.  Since they are seen as
	sub-items, or (if you will) as nested tabs in a web page, each component
	is also the active component in the previous menu.
	
	The last component is not rendered as a menu, but it is taken to be the
	active item in the last menu (that is, the next-to-last component).
	"""
	def __init__(self, menu_path):
		self.menu_path = menu_path

	def render(self, context):
		# Item = (item, follower)
		for i in range(len(self.menu_path)):
			# Strip any single quotes from the string edges
			self.menu_path = [s.rstrip('"\'').lstrip('"\'')
				for s in self.menu_path]
		self.context = context
		# Render each couple: (1,2), (2,3), (3,4), ...
		return ''.join([self._render_menu(self.menu_path[index],	
			active=self.menu_path[index+1], depth=index)
			for index in range(len(self.menu_path)-1)])

	def _render_menu(self, menu_name, active=None, depth=None):
		"""
		If the menu has its own template, then use the template.  Otherwise,
		ask its class to do the rendering.
		"""
		from django.template.loader import get_template
		from django.template import TemplateDoesNotExist
		try:
			menu_template = get_template('menu/%s.html' % menu_name)
			self.context['active'] = active
			return menu_template.render(self.context)
		except TemplateDoesNotExist:
			return menu.render(menu_name, depth=depth, active=active)

def do_menu(parser, token):
	menu_path = token.split_contents()
	return MenuNode(menu_path[1:])

# Usage example:
# {% menu root venue_menu new_visit %}
# will render the 'root' menu with the 'venue_menu' item, if it exists, as
# active; then the 'venue_menu_ menu with the 'new_visit' item, if it
# exists, as active.

register.tag('menu', do_menu)