################################################################
#
#   Albow - Tab Panel
#
################################################################

from pygame import Rect
from widget import Widget
from theme import ThemeProperty, FontProperty
from utils import brighten

class TabPanel(Widget):
	#  pages         [Widget]
	#  current_page  Widget

	tab_font = FontProperty('tab_font')
	tab_height = ThemeProperty('tab_height')
	tab_border_width = ThemeProperty('tab_border_width')
	tab_spacing = ThemeProperty('tab_spacing')
	tab_margin = ThemeProperty('tab_margin')
	tab_fg_color = ThemeProperty('tab_fg_color')
	default_tab_bg_color = ThemeProperty('default_tab_bg_color')
	tab_area_bg_color = ThemeProperty('tab_area_bg_color')
	tab_dimming = ThemeProperty('tab_dimming')
	use_page_bg_color_for_tabs = ThemeProperty('use_page_bg_color_for_tabs')
	
	def __init__(self, pages = None, **kwds):
		Widget.__init__(self, **kwds)
		self.pages = []
		self.current_page = None
		if pages:
			w = h = 0
			for title, page in pages:
				w = max(w, page.width)
				h = max(h, page.height)
				self._add_page(title, page)
			self.size = (w, h)
			self.show_page(pages[0][1])
	
	def content_size(self):
		return (self.width, self.height - self.tab_height)
	
	def content_rect(self):
		return Rect((0, self.tab_height), self.content_size())
	
	def page_height(self):
		return self.height - self.tab_height

	def add_page(self, title, page):
		self._add_page(title, page)
		if not self.current_page:
			self.show_page(page)

	def _add_page(self, title, page):
		page.tab_title = title
		page.anchor = 'ltrb'
		self.pages.append(page)
	
	def remove_page(self, page):
		try:
			i = self.pages.index(page)
			del self.pages[i]
		except IndexError:
			pass
		if page is self.current_page:
			self.show_page(None)
	
	def show_page(self, page):
		if self.current_page:
			self.remove(self.current_page)
		self.current_page = page
		if page:
			th = self.tab_height
			page.rect = Rect(0, th, self.width, self.height - th)
			self.add(page)
			page.focus()
	
	def draw(self, surf):
		self.draw_tab_area_bg(surf)
		self.draw_tabs(surf)
	
	def draw_tab_area_bg(self, surf):
		bg = self.tab_area_bg_color
		if bg:
			surf.fill(bg, (0, 0, self.width, self.tab_height))
	
	def draw_tabs(self, surf):
		font = self.tab_font
		fg = self.tab_fg_color
		b = self.tab_border_width
		if b:
			surf.fill(fg, (0, self.tab_height - b, self.width, b))
		for i, title, page, selected, rect in self.iter_tabs():
			x0 = rect.left
			w = rect.width
			h = rect.height
			r = rect
			if not selected:
				r = Rect(r)
				r.bottom -= b
			self.draw_tab_bg(surf, page, selected, r)
			if b:
				surf.fill(fg, (x0, 0, b, h))
				surf.fill(fg, (x0 + b, 0, w - 2 * b, b))
				surf.fill(fg, (x0 + w - b, 0, b, h))
			buf = font.render(title, True, page.fg_color or fg)
			r = buf.get_rect()
			r.center = (x0 + w // 2, h // 2)
			surf.blit(buf, r)
	
	def iter_tabs(self):
		pages = self.pages
		current_page = self.current_page
		n = len(pages)
		b = self.tab_border_width
		s = self.tab_spacing
		h = self.tab_height
		m = self.tab_margin
		width = self.width - 2 * m + s - b 
		x0 = m
		for i, page in enumerate(pages):
			x1 = m + (i + 1) * width // n #self.tab_boundary(i + 1)
			selected = page is current_page
			yield i, page.tab_title, page, selected, Rect(x0, 0, x1 - x0 - s + b, h)
			x0 = x1
	
	def draw_tab_bg(self, surf, page, selected, rect):
		bg = self.tab_bg_color_for_page(page)
		if not selected:
			bg = brighten(bg, self.tab_dimming)
		surf.fill(bg, rect)
	
	def tab_bg_color_for_page(self, page):
		bg = getattr(page, 'default_tab_bg_color', None)
		if not bg and self.use_page_bg_color_for_tabs:
			bg = page.bg_color
		return bg or self.default_tab_bg_color
	
	def mouse_down(self, e):
		x, y = e.local
		if y < self.tab_height:
			i = self.tab_number_containing_x(x)
			if i is not None:
				self.show_page(self.pages[i])

	def tab_number_containing_x(self, x):
		n = len(self.pages)
		m = self.tab_margin
		width = self.width - 2 * m + self.tab_spacing - self.tab_border_width
		i = (x - m) * n // width
		if 0 <= i < n:
			return i
