import py
import autopath
import threading
import time
import socket

from urlloader import URLLoader

from httpmp2.engine import Engine
from httpmp2.game import Game
from httpmp2.command import Command
from httpmp2 import log
log.MINLEVEL = log.ERROR

class config:
    host = ''
    port = 8082
    framerate = 20
    max_events_per_request = 20
    max_events_in_buffer = 10

class EchoGame(Game):
    def calculate_state(self, framestates, timespent):
        super(EchoGame, self).calculate_state(framestates, timespent)
        self.framestates = framestates

    def get_frame_commands(self):
        for id, framestate in self.framestates.iteritems():
            for name, value in framestate.unknown:
                command = Command(name, value)
                yield (-1, command)

class TestEngine(object):
    def setup_class(cls):
        cls.game = game = EchoGame()
        cls.engine = Engine(config, game)
        for i in range(10):
            try:
                cls.engine.initialize()
                break
            except socket.error, e:
                print 'error opening socket: %s - trying again' % (e,)
            config.port += 1
        else:
            py.test.fail('could not initialize server')

    stop = False
    def run(self):
        while 1:
            if self.stop:
                return
            self.engine.run(count=1)

    def functional_test(self):
        outloader = URLLoader(config, '/out')
        outloader.initialize()

        # going to read headers and id (first line of the response)
        headers = outloader.headers()
        assert '200' in headers[0]

        # read id
        id = outloader.next_line().strip()
        # assert id == '1' # bad check, useless info, but whatever...
        print 'id:', id

        # now we'll send events to the server and test whether they're properly
        # echoed back
        print 'going to open /in'
        inloader = URLLoader(config, '/in', '%s\r\nFF123\r\n' % (id,))
        inloader.initialize()
        headers = inloader.headers()
        assert '204' in headers[0]
        inloader.close()
        echoed = outloader.next_line().strip()
        assert echoed == ':FF:123'

        print 'another try'
        inloader = URLLoader(config, '/in', '%s\r\nFF124\r\n' % (id,))
        inloader.initialize()
        headers = inloader.headers()
        assert '204' in headers[0]
        inloader.close()
        echoed = outloader.next_line().strip()
        assert echoed == ':FF:124'

        print 'now we close the outloader, and re-open'
        outloader.close()
        outloader = URLLoader(config, '/out?channelid=%s' % (id,))
        outloader.initialize()
        headers = outloader.headers()
        assert '200' in headers[0]
        newid = outloader.next_line().strip()
        assert newid == id

        inloader = URLLoader(config, '/in',
                             '%s\r\nCCTest chat message\r\n' % (id,))
        inloader.initialize()
        headers = inloader.headers()
        assert '204' in headers[0]
        inloader.close()
        echoed = outloader.next_line().strip()
        print 'echoed:', echoed
        assert echoed == ':CC:Test chat message'

        print 'let\'s let another client connect and send some events'
        outloader2 = URLLoader(config, '/out')
        outloader2.initialize()
        headers = outloader2.headers()
        assert '200' in headers[0]
        ol2id = outloader2.next_line().strip()
        print 'new id:', ol2id
        assert ol2id > id

        print 'send an event, it should now get echoed on both clients'
        inloader = URLLoader(config, '/in', '%s\r\nFF123\r\n' % (id,))
        inloader.initialize()
        headers = inloader.headers()
        assert '204' in headers[0]
        inloader.close()
        echoed = outloader.next_line().strip()
        print 'echoed on outloader:', echoed
        self.engine.server.poll_next()
        echoed2 = outloader2.next_line().strip()
        print 'echoed on outloader2:', echoed2
        assert echoed == echoed2 == ':FF:123'

        outloader2.close()
        outloader.close()

    def test_functional(self):
        runthread = threading.Thread(target=self.run)
        runthread.start()
        try:
            self.functional_test()
        finally:
            self.stop = True
            self.engine.server.poll_next()
            while runthread.isAlive():
                print 'waiting'
                time.sleep(0.1)
            self.engine.close()


