# This is a widget that handles a go game
# It needs a goban object, and handles it from beginning to end

import os
import gtk

import goban


class GoGame(gtk.HBox):
    """
    This class draws a board and some information about the game (turn, captures, etc).
    It also handles moves and other operations on the goban.
    """

    img_res = None

    def __init__(self, goban, network_mode=False, our_color=None):
        super(GoGame, self).__init__()

        self.goban = goban

        if GoGame.img_res is None:
            GoGame.img_res = _build_img_res()
        self.init_widgets()


    def init_widgets(self):
        # All of this is to create the info box along the right side of the board
        info_box = gtk.VBox()
        info_rows = []
        for i in range(3):
            info_rows.append(gtk.HBox())

        to_move_label = gtk.Label('To Move:')
        black_cap_label = gtk.Label('Black Captures:')
        white_cap_label = gtk.Label('White Captures:')

        self.to_move_value = gtk.Label('None')
        self.black_cap_value = gtk.Label('0')
        self.white_cap_value = gtk.Label('0')

        info_rows[0].pack_start(to_move_label, expand=False, padding=5)
        info_rows[1].pack_start(black_cap_label, expand=False, padding=5)
        info_rows[2].pack_start(white_cap_label, expand=False, padding=5)
        info_rows[0].pack_end(self.to_move_value, expand=False, padding=5)
        info_rows[1].pack_end(self.black_cap_value, expand=False, padding=5)
        info_rows[2].pack_end(self.white_cap_value, expand=False, padding=5)

        for row in info_rows:
            info_box.pack_start(row, expand=False)

        self.pass_button = gtk.Button('Pass')
        self.resign_button = gtk.Button('Resign')
        self.pass_button.connect('clicked', self.on_pass)
        self.resign_button.connect('clicked', self.on_resign)

        info_box.pack_start(self.pass_button, expand=False, padding=10)
        info_box.pack_start(self.resign_button, expand=False, padding=10)

        self.board_area = gtk.DrawingArea()
        self.board_area.set_size_request(800, 800)
        self.board_area.set_events(gtk.gdk.POINTER_MOTION_MASK |
                                   gtk.gdk.POINTER_MOTION_HINT_MASK | 
                                   gtk.gdk.BUTTON_PRESS_MASK | 
                                   gtk.gdk.BUTTON_RELEASE_MASK)

        self.board_area.connect('expose-event', self.draw_board)
        self.board_area.connect('motion-notify-event', self.do_hover)
        self.board_area.connect('button-press-event', self.do_play)

        self.pack_start(self.board_area)
        self.pack_end(info_box, expand=False)

        self.update_info()


    def do_hover(self, widget, event):
        x = event.x
        y = event.y
        width, height = widget.size_request()
        size = min(width, height)
        board_size = self.goban.board_size
        inc = size / board_size

        row = int(y / inc)
        col = int(x / inc)

        if max(row,col) < board_size:
            if self.goban._real_pos((row,col)) != self.goban.hover:
                self.goban.set_hover((row,col))
                self.board_area.queue_draw()
        else:
            self.goban.clear_hover()
            self.board_area.queue_draw()


    def do_play(self, widget, event):
        x = event.x
        y = event.y
        width, height = widget.size_request()
        size = min(width, height)
        board_size = self.goban.board_size
        inc = size / board_size

        row = int(y / inc)
        col = int(x / inc)

        self.goban.play_move((row,col))
        self.update_info()


    # fixme: create a backbuffer pixmap and draw to *that* when we need to update
    # the board, then just use *this* to print that to the DrawingArea...
    def draw_board(self, widget, event):
        gc = widget.get_style().fg_gc[gtk.STATE_NORMAL]
        drawable = widget.window
        # pixmap = gtk.gdk.Pixmap(window, width, height, depth=-1)

        width, height = widget.size_request()
        size = min(width, height)
        board_size = self.goban.board_size
        inc = size / board_size

        for i in range(len(self.goban.board)):
            # Get the right image and scale it
            base_img = GoGame.img_res[self.goban.draw_code(i)]
            img = base_img.scale_simple(inc, inc, gtk.gdk.INTERP_BILINEAR)

            row = i / board_size
            col = i % board_size
            drawable.draw_pixbuf(gc, img, 0, 0, inc * col, inc * row, inc, inc)

            if i == self.goban.hover:
                if self.goban.to_move == goban.Goban.BLACK:
                    code = 'bH'
                elif self.goban.to_move == goban.Goban.WHITE:
                    code = 'wH'

                base_img = GoGame.img_res[code]
                img = base_img.scale_simple(inc, inc, gtk.gdk.INTERP_BILINEAR)
                drawable.draw_pixbuf(gc, img, 0, 0, inc * col, inc * row, inc, inc)




    def on_pass(self, widget):
        self.goban.pass_move()
        self.update_info()


    def on_resign(self, widget):
        self.goban.resign()
        self.update_info()


    # fixme: Add a widget to show the outcome
    def update_info(self):
        if self.goban.to_move == goban.Goban.BLACK:
            move = 'Black'
        elif self.goban.to_move == goban.Goban.WHITE:
            move = 'White'
        else:
            move = 'None'
        self.to_move_value.set_text(move)
        self.black_cap_value.set_text(str(self.goban.black_captures))
        self.white_cap_value.set_text(str(self.goban.white_captures))




def _magnitude(vector):
    x,y = vector
    return math.sqrt(x*x + y*y)


def _build_img_res():
    ret = {}
    
    triangle = _load_png('go_t.png')
    circle = _load_png('go_c.png')
    
    ret['wH'] = _load_png('go_wH.png')
    ret['bH'] = _load_png('go_bH.png')

    ret['wT'] = _load_png('go_w.png')
    width = ret['wT'].get_width()
    height = ret['wT'].get_height()
    triangle.composite(ret['wT'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255)

    ret['bT'] = _load_png('go_b.png')
    width = ret['bT'].get_width()
    height = ret['bT'].get_height()
    triangle.composite(ret['bT'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255)

    for d in ('u', 'd', 'l', 'r', 'm', 'dl', 'dr', 'ul', 'ur', 'h', 'w', 'b'):
        ret[d] = _load_png('go_' + d + '.png')

        ret[d + 'C'] = _load_png('go_' + d + '.png')
        width = ret[d + 'C'].get_width()
        height = ret[d + 'C'].get_height()
        circle.composite(ret[d + 'C'], 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255)
        
    return ret


def _load_png(name):
    """ Load image and return image object"""
    fullname = os.path.join('ui/res/', name)
    image = gtk.gdk.pixbuf_new_from_file(fullname)

    # if alpha is not None:
    #     image = _set_alpha(image, alpha)

    return image


# _trans_png = None

# def _set_alpha(image, alpha):
#      """
#      change_opacity - changes the opacity of pixbuf by combining
#      the pixbuf with a pixbuf derived from a transparent .png

#      returns: a pixbuf of image made alpha more composite
#      """
     
#      global _trans_png

#      if _trans_png == None:
#          _trans_png = _load_png('transparent.png')

#      width = image.get_width()
#      height = image.get_height()

#      trans= _trans_png.scale_simple(width,height,gtk.gdk.INTERP_NEAREST)
#      trans.composite(image, 0, 0, width, height, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, alpha)
#      return trans