#!/usr/bin/python
from new import classobj, instancemethod
from os import mkfifo, unlink, path
import sys

class Remote(type):
    def __init__(cls, name, bases, d):
        type.__init__(cls, name, bases, d)
        d['shutdown'] = None # Dummy message
        cls.Stub = cls.mkstub(name, d.keys())

    def mkstub(cls, name, msgs):
        Stub = classobj(name+"Stub", (), {})
        def mksend(msg):
            def send(self):
                self.fifo.write(msg+"\n")
                self.fifo.flush()
            return instancemethod(send, None, Stub)
        for msg in msgs:
            setattr(Stub, msg, mksend(msg))
        return Stub

    def openClient(cls, fname):
        stub = cls.Stub()
        stub.fifo = open(fname, 'a')
        return stub

    def handle(cls, fname, srv):
        while True:
            try:
                f = open(fname, 'r')
                for l in f:
                    msg = l[:-1]
                    if msg == 'shutdown':
                        f.close()
                        unlink(fname)
                        return;
                    else:
                        method = getattr(srv, msg)
                        method()
            except StopIteration: continue

    def startServer(cls, fname):
        if path.exists(fname):
            unlink(fname)
        mkfifo(fname)
        srv = cls()
        cls.handle(fname, srv)


class Demo:
    __metaclass__ = Remote
    def foo(self):
        print "Foo"
    def goo(self):
        print "Goo"

opt = sys.argv[1]
fname = sys.argv[2]
if opt == "server":
    Demo.startServer(fname)
elif opt == "client":
    d = Demo.openClient(fname)
    d.foo()
    d.goo()
    d.shutdown()

