#!/usr/bin/env python
# coding: utf-8
"""
My first test with pygame and twisted
network part

(c) by Julian Habrock, 23.1.09
bytemuehle.de
"""

import sys

from pygame import time

from twisted.internet import reactor
from twisted.spread import pb

import simple_game

help1 = """
twisted PyGame
================
usage: 
$python twisted_game.py [arg]

arg must be one of:
'server' or 's' to start the server
'client' or 'c' to start the client

-----------
(c) by Julian Habrock 
bytemuehle.de"""

help2 = """
arg must be one of:
'server' or 's' to start the server
'client' or 'c' to start the client
"""

if len(sys.argv) != 2:
    print help1
    START_SERVER = None
else:
    arg = sys.argv[1]
    if arg in ("server", "s"):
        START_SERVER = True
    elif arg in ("client", "c"):
        START_SERVER = False
    else:
        print help2
        START_SERVER = None

def clientfunc(func):
    def dummy(*args):pass
    if not START_SERVER:
        return func
    else: return dummy

def serverfunc(func):
    def dummy(*args):pass
    if not START_SERVER:
        return dummy    
    else: return func

class PygameTimer(pb.Root):
    def __init__(self, factory=None):
        self.clock = time.Clock()
        self.game = simple_game.Game()
        self.factory = factory
        if not START_SERVER:
            assert self.factory != None
        self.update_game()

    def update_game(self):
        """
        replaces the pygame event loop
        """        
#        self.clock.tick()
#        self.ms = self.clock.get_rawtime()

#        framespeed = (1.0/100.0) * 1000
#        lastspeed = self.ms
#        next = framespeed - lastspeed

#        print "framespeed", framespeed, "ms", self.ms, "next", next, "fps",\
#                                                         self.clock.get_fps()
        self.get_pos()
        self.game.update()
        self.send_pos()
        
                
        if self.game.running:
            reactor.callLater(0.05, self.update_game)
        else:
            reactor.stop()
            
        
    def setpos(self, pos):
        self.game.player2.position = pos
    
    def dummy(self, *args):
        print "dummy: ", args

            
    # CLIENT PART
    @clientfunc
    def send_pos(self):
        d = factory.getRootObject()
        d.addCallback(lambda object: object.callRemote('setpos',
                                                    self.game.player.position))    

    @clientfunc                                
    def get_pos(self):
        d = factory.getRootObject()
        d.addCallback(lambda object: object.callRemote('getpos'))
        d.addCallback(self.setpos)


    # SERVER PART
    @serverfunc
    def remote_getpos(self):
        #print 'getdir'
        return self.game.player.position
    
    @serverfunc
    def remote_setpos(self, new_pos):
        #print "setting position: ", new_pos
        self.game.player2.position = new_pos
        return True
    
    

if __name__ == '__main__' and START_SERVER is not None:
    if START_SERVER:
        pt = PygameTimer()
        reactor.listenTCP(8789, pb.PBServerFactory(pt))
    else:
        factory = pb.PBClientFactory()
        pt = PygameTimer(factory)
        reactor.connectTCP("localhost", 8789, factory)
    reactor.run()
    

