#!/usr/bin/python

#mport os
import sys
import time
import getopt

#mport gtp
import ishi
import goban
import player

def usage():
    sys.stderr.write(sys.argv[0]+'\n')
    sys.stderr.write('\t-h (gives help)\n')
    sys.stderr.write('\t-w {human|gtp} (default gtp)\n')
    sys.stderr.write('\t-b {human|gtp} (default gtp)\n')
    sys.stderr.write('\t-B boardsize (default 9)\n')
    sys.stderr.write('\t-k komi (default 6.5 for a handicap 0, 0.5 for others)\n')
    sys.stderr.write('\t-H handicap (default 0)\n')
    sys.stderr.write('\t-x white program (default "gnugo --mode gtp")\n')
    sys.stderr.write('\t-y black program (default "gnugo --mode gtp")\n')
    sys.stderr.write('\t-t (gives a text mode)\n')
    sys.stderr.write('\t-W (uses weak illegal move checking)\n')
    sys.exit(1)

def main():
    #x,y = 0,0
#    while 1:
#        #Draw Everything
#        screen.blit(background, (0, 0))
#        (x,y) = pygame.mouse.get_pos()
#        pygame.event.pump()
#        #pygame.mouse.set_visible(0)
#        #x += 1
#        #y += 1
#        #print x,y
#        screen.blit(black_image, (x, y))
#        pygame.display.flip()
#        clock.tick(60)
    prog_black='gnugo --mode gtp'
    prog_white='gnugo --mode gtp'
    boardsize = 9
    #komi = 6.5
    komi_given = False
    handicap = 0
    pause_time = 2
    Player = ['gtp','gtp']
    try:
        optlist, args = getopt.getopt(sys.argv[1:], 'w:b:B:k:h:tx:y:WH:')
    except:
        sys.stderr.write('Unrecognized option\n')
        usage()
    #white_done = 0
    #black_done = 0
    human = 0
    text_mode = 0
    weak_validity_check = 0
    for opt in optlist:
        if opt[0] == '-t':
            text_mode = 1
        elif opt[0] == '-H':
            handicap = int(opt[1])
        elif opt[0] == '-w':
            if opt[1] == 'human' or opt[1] == 'h':
                Player[ishi.white] = 'human'
                human += 1
            elif opt[1] == 'gtp':
                Player[ishi.white] = 'gtp'
            else:
                usage()
        elif opt[0] == '-b':
            if opt[1] == 'human' or opt[1] == 'h':
                Player[ishi.black] = 'human'
                human += 1
            elif opt[1] == 'gtp':
                Player[ishi.black] = 'gtp'
            else:
                usage()
        elif opt[0] == '-B':
            try:
                boardsize = int(opt[1])
            except:
                usage()
        elif opt[0] == '-k':
            try:
                komi = float(opt[1])
                komi_given = True
            except:
                usage()
        elif opt[0] == '-h':
            usage()
        elif opt[0] == '-x':
            prog_white = opt[1]
        elif opt[0] == '-y':
            prog_black = opt[1]
        elif opt[0] == '-W':
            weak_validity_check = 1

    if human > 1:
        sys.stderr.write('Only one human player allowed\n')
        sys.exit(1)

    if not komi_given:
        if handicap == 0:
            komi = 6.5
        else:
            komi = 0.5
    if not text_mode:
        # with these import's, we're making an effort to make it so
        # text mode users don't have to have pygame installed
        # however, this independence is untested.  A threaded python
        # interpreter shouldn't be required for the text mode either
        import pygame
        import pygamehelper
        import pygame.sprite
        import pygame.transform
        import pygame.image
        import pygame.draw
        import pygame.locals
        import pygame.font
        #import pygamehelper
        import pe
        import guigoban

        #Initialize Everything GUI-related
        pygame.init()
        # hoping this is just smaller than a 1024x768 screen, with window
        # borders
        screen = pygame.display.set_mode((1004, 748))
        pygame.display.set_caption('Pygame Go')
        #pygame.mouse.set_visible(0)

        def pump():
            if pygame.event is not None:
                pygame.event.pump()

        PE = pe.PeriodicExecutor(0.02, pump)
        PE.start()

        # amount by which to displace text relative to the board
        spacing = 20

        background_color = (128, 128, 128)

        # some sounds.  There's more in the board stuff for stone clicks
        error_sound = pygamehelper.load_sound('error.wav')
        pass_sound = pygamehelper.load_sound('pass.wav')

        # font stuff.  More below.
        font = pygame.font.Font(None, 36)
        pass_text = font.render("Pass", 1, (128, 10, 10))
        quit_text = font.render("Quit", 1, (128, 10, 10))

        #Create The Backgound
        background = pygame.Surface(screen.get_size())
        background.fill(background_color)

        #Put Text On The Background, Centered
    #    text = font.render("White vs. Black", 1, (10, 10, 10))
    #    text_pos = text.get_rect()
    #    text_pos.centerx = background.get_rect().centerx
    #    background.blit(text,text_pos)

        #Display The Background
        screen.blit(background, (0, 0))
        pygame.display.flip()

        #Prepare Game Objects
        #clock = pygame.time.Clock()

        black_image, black_rect = pygamehelper.load_image('white.png', -1)

    #print 'prog_white is',prog_white
    #print 'prog_black is',prog_black
    # initialize players
    if Player[ishi.black] == 'gtp':
        Player[ishi.black] = \
            player.player(1,0,prog_black,boardsize,komi,handicap,text_mode)
    elif Player[ishi.black] == 'human':
        Player[ishi.black] = \
            player.player(0,1,'human',boardsize,komi,handicap,text_mode)
    else:
        raise 'bad thing in player initialization 1'
    if Player[ishi.white] == 'gtp':
        Player[ishi.white] = \
            player.player(1,0,prog_white,boardsize,komi,handicap,text_mode)
    elif Player[ishi.white] == 'human':
        Player[ishi.white] = \
            player.player(0,1,'human',boardsize,komi,handicap,text_mode)
    else:
        raise 'bad thing in player initialization 2'

    if text_mode:
        board = goban.board(boardsize,handicap)
    else:
        board = guigoban.guiboard(boardsize,handicap)

    # add handicap stones.
    # no attempt is made to get two gtp clients to agree on this
    # yet.  Humans ignore it, and we pick the first gtp client
    # that gives us this info
    for color in [ishi.black,ishi.white]:
        if Player[color].gtp_flag:
            for pos in Player[color].stuff.hcap_list:
                board.move(pos,ishi.black)
            break

    passcount = 0
    first_time = 1
    if handicap < 2:
        move_order = [ishi.black,ishi.white]
    else:
        move_order = [ishi.white,ishi.black]
    #Main Loop
    white_caps_text = None
    black_caps_text = None
    komi_text = None
    handicap_text = None
    white_caps_text_pos = None
    black_caps_text_pos = None
    komi_text_pos = None
    handicap_text_pos = None
    while True:
        for state in move_order:
            if text_mode:
                print
                print board
            else:
                stones_pos = board.gen_rect()
                stones_pos.center = screen.get_rect().center
                stones_offset = stones_pos.topleft
                stones = board.gen_surface(stones_offset)
                #stones_pos.topleft = stones_offset
                #print stones
                screen.blit(stones,stones_pos)

                #print board
                #print

                pass_text_pos = pass_text.get_rect()
                pass_text_pos.topleft = stones_pos.topright
                pass_text_pos.move_ip(spacing,0)
                board.pass_text_pos = pass_text_pos
                screen.blit(pass_text, pass_text_pos)

                quit_text_pos = quit_text.get_rect()
                quit_text_pos.topleft = pass_text_pos.bottomleft
                board.quit_text_pos = quit_text_pos
                screen.blit(quit_text, quit_text_pos)

                if first_time:
                    first_time = 0
                else:
                    # erase what was there before
                    white_caps_text.fill(background_color)
                    screen.blit(white_caps_text, white_caps_text_pos)
                    black_caps_text.fill(background_color)
                    screen.blit(black_caps_text, black_caps_text_pos)
                    komi_text.fill(background_color)
                    screen.blit(komi_text, komi_text_pos)
                    handicap_text.fill(background_color)
                    screen.blit(handicap_text, handicap_text_pos)

            if text_mode:
                print
                print 'White caps',Player[ishi.white].caps
                print 'Black caps',Player[ishi.black].caps
                print 'Komi',komi
                print 'Handicap',handicap
            else:
                white_caps_text = font.render( \
                    'White caps: '+str(Player[ishi.white].caps), 1, \
                    (250, 250, 250))
                white_caps_text_pos = white_caps_text.get_rect()
                white_caps_text_pos.topright = stones_pos.topleft
                white_caps_text_pos.move_ip(-spacing,0)
                screen.blit(white_caps_text, white_caps_text_pos)

                black_caps_text = font.render( \
                    'Black caps: '+str(Player[ishi.black].caps), 1, \
                    (5, 5, 5))
                black_caps_text_pos = black_caps_text.get_rect()
                black_caps_text_pos.topright = white_caps_text_pos.bottomright
                screen.blit(black_caps_text, black_caps_text_pos)

                komi_text = font.render( \
                    'Komi: '+str(komi), 1, (10, 128, 10))
                komi_text_pos = komi_text.get_rect()
                komi_text_pos.topright = black_caps_text_pos.bottomright
                screen.blit(komi_text, komi_text_pos)

                handicap_text = font.render( \
                    'Handicap: '+str(handicap), 1, \
                    (10, 128, 10))
                handicap_text_pos = handicap_text.get_rect()
                handicap_text_pos.topright = komi_text_pos.bottomright
                screen.blit(handicap_text, handicap_text_pos)

                pygame.display.flip()
                time.sleep(pause_time)

            while True:
                position = Player[state].get_input(state,board)
                if position == 'QUIT':
                    PE.func = None
                    PE.active = False
                    sys.exit(0)
                if position != 'PASS':
                    # ask the other player if this is a legal move
                    if weak_validity_check:
                        valid = not board.taken(position)
                    else:
                        valid = \
                            Player[ishi.invert(state)].is_legal(board,state,position)
                    if valid:
                        break
                    else:
                        if text_mode:
                            sys.stdout.write(chr(7)+'Illegal move\n')
                        else:
                            error_sound.play()
                            #time.sleep(pause_time)
                else:
                    break
            if position == 'PASS':
                if text_mode:
                    print 'Pass'
                else:
                    pass_sound.play()
                    #time.sleep(pause_time)
                passcount += 1
            else:
                (current_caps,opponent_caps) = board.move(position,state)
                Player[state].caps += current_caps
                Player[ishi.invert(state)].caps += opponent_caps
                #print Player[ishi.white].caps,Player[ishi.black].caps

                if not text_mode:
                    board.stone_sound.play()
                passcount = 0
            Player[ishi.invert(state)].feed_move(state,position)
            if passcount == 2:
                break
            # this slows things down of course, but it deters multiple mouseclicks
            # (which feel like a single click to the user) on the same spot making
            # more than one sound
            if not text_mode:
                pass
                #time.sleep(pause_time)
        if passcount == 2:
            break
    estimate = 'no estimate'
    for state in [ishi.black,ishi.white]:
        t = Player[state].get_result()
        if t != 'no estimate':
            estimate = t
#        print ishi.description(state),'estimates',\
#            Player[state].get_result()
#    while 1:
#        screen.blit(stones,stones_pos)
#        pygame.display.flip()
    if text_mode:
        print 'Result:',estimate
        sys.exit(0)
    else:
        result_text = font.render('Result: '+estimate, 1, (10, 128, 10))
        result_text_pos = result_text.get_rect()
        result_text_pos.midbottom = stones_pos.midtop
        ##result_text_pos.topleft = screen.get_rect().topleft
        result_text_pos.move_ip(0,-spacing)
        screen.blit(result_text,result_text_pos)
        pygame.display.flip()
        while 1:
            (b1,b2,b3) = pygame.mouse.get_pressed()
            pygame.event.pump()
            if b1:
                (mx,my) = pygame.mouse.get_pos()
                pygame.event.pump()
                if quit_text_pos.collidepoint(mx,my):
                    sys.exit(0)
            time.sleep(0.05)

#Game Over

#def text_main():
#    board = goban.board(9)
#    print board

#this calls the 'main' function when this script is executed
if __name__ == '__main__': main()