import pygame
import gfx, ticker, village

images = ['goldcoin', 'clock_long', 'clock_mid', 'clock_short']
sounds = ['click']



def render_gold(numcoins, optimize=1):
    coin = images.goldcoin
    w = ((numcoins / 5) + 1) * (coin.get_width() - 3) + 2
    h = coin.get_height() + 5 * 3
    img = pygame.Surface((w, h))
    for x in range(numcoins):
    	posx = (x / 5) * (coin.get_width() - 3)
	posy = (4 - (x%5)) * 3
    	img.blit(coin, (posx, posy))
    img.set_colorkey(0)
    if optimize:
    	img = gfx.optimize(img)
    return img

def get_clock(time):
    if time < 12000:
    	return images.clock_short
    if time < 24000:
    	return images.clock_mid
    return images.clock_long


def render_list(*images):
    w, h = -5, 0
    for i in images:
    	 w += i.get_width() + 5
	 h = max(h, i.get_width())
    img = pygame.Surface((w, h))
    cc = 255,0,0
    img.fill(cc)
    h /= 2
    w = 0
    for i in images:
    	r = gfx.position(i, midleft=(w,h))
	img.blit(i, r)
	w += i.get_width() + 5
    img.set_colorkey(cc)
    return img


tiptitle_font = None
tipdescr_font = None
def render_tooltip(title, icons, description, textcolor, backcolor):
    global tiptitle_font, tipdescr_font
    if not tiptitle_font:
    	tiptitle_font = pygame.font.Font(None, 18)
    	tipdescr_font = pygame.font.Font(None, 15)

    w, h = 0, 10
    if title:
    	titleimg = tiptitle_font.render(title, 1, textcolor, backcolor)
	w += titleimg.get_width() + 10
	h += titleimg.get_height()
    if icons:
    	iconimg = render_list(*icons)
	w = max(w, iconimg.get_width())
	h += iconimg.get_height()
    if description:
    	dw = max(w, 160)
	descrimg = pygame.Surface((dw, 600))
	descrimg.fill(backcolor)
	dh = render_textrect(descrimg, description, tipdescr_font, descrimg.get_rect(),
	    	textcolor, backcolor, 1)
	w = dw
	h += dh

    tipimage = pygame.Surface((w,h))
    tipimage.fill(backcolor)
    colorkey = 255,0,255
    fill_corners(tipimage, colorkey, tipimage.get_rect())
    x,y = w/2, 5
    if title:
    	r = gfx.position(titleimg, midtop=(x,y))
	tipimage.blit(titleimg, r)
	y += r.height
    if icons:
    	r = gfx.position(iconimg, midtop=(x,y))
	tipimage.blit(iconimg, r)
	y += r.height
    if description:
    	r = gfx.position(descrimg, midtop=(x,y))
	src = descrimg.get_rect()
	src.height = dh
	tipimage.blit(descrimg, r, src)

    tipimage.set_colorkey(colorkey)
    return gfx.optimize(tipimage)
    

title_font = None
def draw_titlebar(img, color, background, rect, text, icon=None):
    global title_font
    if not title_font: title_font = pygame.font.Font(None, 30)
    
    rect = pygame.Rect(rect)
    rect.h = 30
    fill_noncorners(img, color, rect)
    text = title_font.render(text, 1, background, color)
    pos = rect.left + 16, rect.top + 2
    img.blit(text, pos)

    if icon:
    	r = gfx.position(icon, topright=rect.topright)
	img.blit(icon, r)


def draw_button_norm(img, rect, icon, color):
    r = gfx.position(icon, center=rect.center)
    img.blit(icon, r)

def draw_button_hilight(img, rect, icon, color):
    outline_noncorners(img, color, rect)
    r = gfx.position(icon, center=rect.move(-1,-1).center)
    img.blit(icon, r)

def draw_button_push(img, rect, icon, color):
    rect = rect.move(1, 1)
    fill_noncorners(img, color, rect)
    r = gfx.position(icon, center=rect.center)
    img.blit(icon, r)

def draw_button_abort(img, rect, icon, color):
    rect = rect.move(1, 1)
    outline_noncorners(img, color, rect)
    r = gfx.position(icon, center=rect.center)
    img.blit(icon, r)


def blit_noncorners(dst, src, (x,y)):
    w,h = src.get_size()
    dst.blit(src, (x+3, y), (3, 0, w-6, 1))
    dst.blit(src, (x+1, y+1), (1, 1, w-2, 2))
    dst.blit(src, (x, y+3), (0, 3, w, h-6))
    dst.blit(src, (x+1, h-3), (1, h-1, w-2, 2))
    dst.blit(src, (x+3, h-1), (3, h-1, w-6, 1))

def fill_corners(dst, color, rect):
    c = dst.map_rgb(color)
    size = 1, 1
    dst.fill(c, ((rect.left, rect.top), size))
    dst.fill(c, ((rect.right-1, rect.top), size))
    dst.fill(c, ((rect.left, rect.bottom-1), size))
    dst.fill(c, ((rect.right-1, rect.bottom-1), size))
    
def fill_noncorners(dst, color, rect):
    x,y,w,h = rect
    c = dst.map_rgb(color)
    dst.fill(c, (x+3, y, w-6, 1))
    dst.fill(c, (x+1, y+1, w-2, 2))
    dst.fill(c, (x, y+3, w, h-6))
    dst.fill(c, (x+1, y+h-3, w-2, 2))
    dst.fill(c, (x+3, y+h-1, w-6, 1))

def fill_noncorners_buttopleft(dst, color, rect):
    x,y,w,h = rect
    c = dst.map_rgb(color)
    dst.fill(c, (x, y, w-3, 1))
    dst.fill(c, (x, y+1, w-1, 2))
    dst.fill(c, (x, y+3, w, h-6))
    dst.fill(c, (x+1, y+h-3, w-2, 2))
    dst.fill(c, (x+3, y+h-1, w-6, 1))


def fill_noncorners_buttopright(dst, color, rect):
    x,y,w,h = rect
    c = dst.map_rgb(color)
    dst.fill(c, (x+3, y, w-3, 1))
    dst.fill(c, (x+1, y+1, w-1, 2))
    dst.fill(c, (x, y+3, w, h-6))
    dst.fill(c, (x+1, y+h-3, w-2, 2))
    dst.fill(c, (x+3, y+h-1, w-6, 1))

def outline_noncorners(dst, color, rect):
    x,y,w,h = rect
    c = dst.map_rgb(color)
    dst.fill(c, (x+3, y, w-5, 2))
    dst.fill(c, (x+1, y+1, 2, 2))
    dst.fill(c, (x+w-2, y+1, 2, 2))
    dst.fill(c, (x, y+3, 2, h-6))
    dst.fill(c, (x+w-1, y+3, 2, h-6))
    dst.fill(c, (x+1, y+h-3, 2, 2))
    dst.fill(c, (x+w-2, y+h-3, 2, 2))
    dst.fill(c, (x+3, y+h-2, w-5, 2))

    
class Button:
    def __init__(self, icon, rect, tooltip=None, color=(30, 30, 50),
    	    	 callback=None, *args):
    	self.rect = pygame.Rect(rect)
	self.icon = icon
	self.disabled_icon = gfx.ghost(icon)
	self.tooltip = tooltip
	self.hilite = 0
	self.pushed = 0
	self.color = color
	self.tippos = 0,0
	self.disabled = 0
	self.callback = callback
	self.args = args
	

    def mousemoved(self, pos):
    	self.hilite = self.rect.collidepoint(pos)
	self.tippos = pos[0]+18, pos[1]+32
	return self.hilite

    def mousepushed(self, pos):
    	if not self.disabled:
    	    if self.hilite:
		self.pushed = 1
	    return self.hilite

    def mousereleased(self, pos):
    	if not self.disabled:
    	    washit = self.hilite
	    self.pushed = self.hilite = 0
	    if washit and self.callback:
		self.callback(*self.args)
		sounds.click.play()
	    return washit

    def draw(self, screen):
    	if self.disabled:
	    draw_button_norm(screen, self.rect, self.disabled_icon, self.color)
    	else:
    	    if not self.hilite and not self.pushed:
		draw_button_norm(screen, self.rect, self.icon, self.color)
	    elif not self.pushed:
		draw_button_hilight(screen, self.rect, self.icon, self.color)
	    elif not self.hilite:
		draw_button_abort(screen, self.rect, self.icon, self.color)
	    else:
		draw_button_push(screen, self.rect, self.icon, self.color)
	
	if self.hilite and self.tooltip:
	    screen.blit(self.tooltip, self.tippos)
    	

class BuildingButton(Button):
    def __init__(self, building, image, tipname, gold, time, tipdescription, fastcallback=None, donecallback=None):
    	icons = render_gold(abs(gold)), get_clock(time)
    	tip = render_tooltip(tipname, icons, tipdescription,
	    	    (30, 30, 50), (200, 180, 30))
	if image.get_size() != (26, 26):
	    image = pygame.transform.scale(image, (26, 26))
	Button.__init__(self, image, (0,0,40,30), tip, (200, 180, 30), self.launchtimertask)
    	self.goldneeded = gold
	self.timeneeded = time
	self.donecallback = donecallback
	self.fastcallback = fastcallback
	self.fullimage = image
	self.building = building

    def launchtimertask(self):
    	image = pygame.transform.scale(self.fullimage, (20, 20))
	tick = self.taskticker = ticker.Ticker(self.timeneeded)
	task = village.TimedTask(tick, image, 4, self.finishedtimer)
	self.building.village.addtask(task)
	self.building.village.changegold(-self.goldneeded)
    	if self.fastcallback: self.fastcallback()

    def finishedtimer(self):
	if self.donecallback: self.donecallback()



class BuildingButtonSimple(Button):
    def __init__(self, building, image, tipname, tipdescription, callback=None):
    	tip = render_tooltip(tipname, None, tipdescription,
	    	    (30, 30, 50), (200, 180, 30))
	if image.get_size() != (30,30):
    	    image = pygame.transform.scale(image, (30, 30))
	Button.__init__(self, image, (0,0,40,30), tip, (200, 180, 30), callback)
    	self.goldneeded = 0
	self.timeneeded = 0
	self.fullimage = image
	self.building = building




#this was originally from the pygame code repository.
#it does text wordwrapping. changed to output directly to destination

def render_textrect(surface, string, font, rect, text_color, background_color, justification=0):

    import pygame
    
    final_lines = []

    requested_lines = string.splitlines()

    # Create a series of lines that will fit on the provided
    # rectangle.

    for requested_line in requested_lines:
        if font.size(requested_line)[0] > rect.width:
            words = requested_line.split(' ')
            # if any of our words are too long to fit, return.
            for word in words:
                if font.size(word)[0] >= rect.width:
                    raise ValueError, "The word " + word + " is too long to fit in the rect passed."
            # Start a new line
            accumulated_line = ""
            for word in words:
                test_line = accumulated_line + word + " "
                # Build the line while the words fit.    
                if font.size(test_line)[0] < rect.width:
                    accumulated_line = test_line
                else:
                    final_lines.append(accumulated_line)
                    accumulated_line = word + " "
            final_lines.append(accumulated_line)
        else:
            final_lines.append(requested_line)

    # Let's try to write the text out on the surface.
    xpos, ypos = rect.topleft

    accumulated_height = rect.top
    for line in final_lines:
        if line != "":
            tempsurface = font.render(line, 1, text_color, background_color)
	    tempw = tempsurface.get_width()
            if justification == 0:
                surface.blit(tempsurface, (xpos, accumulated_height))
            elif justification == 1:
                surface.blit(tempsurface, (xpos+(rect.width - tempw) / 2, accumulated_height))
            elif justification == 2:
                surface.blit(tempsurface, (xpos+rect.width - tempw, accumulated_height))
            else:
                raise TextRectException, "Invalid justification argument: " + str(justification)
        accumulated_height += font.size(line)[1] - 3

    return accumulated_height


