#!/usr/bin/python

import unittest
import sys
import os
import time
import random

sys.path.append((os.path.dirname(__file__) or '.') + '/..')
from gameclock.game import *

class AbstractGameTest(unittest.TestCase):

    game_type = None # to override autodetection
    settings  = {}   # to override default game settings

    """
    This is the base classe for all clock tests and shouldn't be used directly.
    """
    def setUp(self):
        # strip out the "Test" part to guess the class name of the game to test
        self.game_type = self.game_type or getattr(gameclock.game, self.__class__.__name__.split('Test')[0])
        self.game = self.game_type(**self.settings)

class RegularChessGameTest(AbstractGameTest):
    """basic chess games tests"""

    def test_defaulttime(self):
        """just a basic test to check that the class works"""
        self.assertEqual(self.game.time, self.game_type.time)

    def test_started(self):
        """test if the game starts and is running"""
        self.game.start()
        self.assertTrue(self.game.running())

    def test_count_players(self):
        """test if count_players returns the expected number of players"""
        self.assertEqual(self.game.players, self.game_type.players)

    def test_alive(self):
        """a game just started should be alive"""
        self.assertFalse(self.game.dead())

class AbsurdGameTest(AbstractGameTest):
    """tests for a game with an absurdly small clock time"""

    def setUp(self):
        self.game = RegularChessGame(time = 100)

    def test_dies(self):
        self.game.start()
        time.sleep(0.150) # 100 ms should cross the above 100ms
        self.assertTrue(self.game.dead())

class SimpleGameTest(AbstractGameTest):
    """some simple tests for a game that shouldn't be tested on all games"""

    game_type = RegularChessGame

    def test_set_time(self):
        time = random.randint(0, 10000)
        self.game.set_time(time)
        c = self.game.first_clock
        while c:
            self.assertEqual(c.time, time)
            c = c.next

    def test_resize_back_to_first(self):
        """test that we go back to the first clock after 3 moves"""
        self.game.resize(3)
        self.assertEqual(self.game.first_clock, self.game.cur_clock, "safety check, this should not fail")
        self.game.move()
        self.game.move()
        self.game.move()
        self.assertEqual(self.game.first_clock, self.game.cur_clock, "we should have gone back to the first clock")

    def test_nice_name(self):
        self.assertEqual(RegularChessGame.nice_name(), _('Chess: Regular'))

class LightningChessGameTest(RegularChessGameTest):
    """test the new blitz game type"""
    pass

class FischerChessGameTest(RegularChessGameTest):
    def test_delay(self):
        self.assertEqual(self.game.delay, self.game_type.delay)

class ThreePlayerGameTest(AbstractGameTest):
    settings = { 'players': 3, 'time': 60000 }
    game_type = RegularChessGame

    def test_back_to_first(self):
        """test that we go back to the first clock after 3 moves"""
        self.game.move()
        self.game.move()
        self.game.move()
        self.assertEqual(self.game.first_clock, self.game.cur_clock)

class OnePlayerGameTest(SimpleGameTest):
    settings = { 'players': 1, 'time': 3600000 }
    game_type = RegularChessGame

    def test_back_to_first(self):
        """test that we go back to the first clock after 3 moves"""
        self.game.move()
        self.assertEqual(self.game.first_clock, self.game.cur_clock)
        self.game.move()
        self.assertEqual(self.game.first_clock, self.game.cur_clock)
        self.game.move()
        self.assertEqual(self.game.first_clock, self.game.cur_clock)

    def test_resize(self):
        self.game = RegularChessGame(time = 100)
        self.game.resize(1)
        i = 0
        p = self.game.first_clock
        while p:
            p = p.next
            i += 1
        self.assertEqual(i, self.game.players)
        self.assertEqual(i, 1)

class GoStandardByoyomiGameTest(AbstractGameTest):
    settings = { 'players': 2, 'time': 100, 'byoyomi': 5 }

    def test_change_byoyomi(self):
        self.game.set_byoyomi(self.settings['byoyomi'] - 1)
        self.assertFalse(self.game.cur_clock.is_byoyomi())
        self.game.set_byoyomi(self.settings['byoyomi'] + 1)
        self.assertFalse(self.game.cur_clock.is_byoyomi())
