#!/usr/bin/env python

# based on the 'calculator' demo in the Thrift source

import sys, os.path
sys.path.insert(0, os.path.join(os.path.abspath(os.path.split(sys.argv[0])[0]), 'gen-py'))
import tutorial.Calculator
from tutorial.ttypes import InvalidOperation, Operation
from thrift.transport import TTwisted
from thrift.protocol import TBinaryProtocol

from twisted.internet import reactor, defer

from zope.interface import implements


class CalculatorHandler(object):
    implements(tutorial.Calculator.Iface)

    operations = {
        Operation.ADD: int.__add__,
        Operation.SUBTRACT: int.__sub__,
        Operation.MULTIPLY: int.__mul__,
        Operation.DIVIDE: int.__div__,
    }

    def _dispatchWork(self, w):
        # Just assume that it may take a long time
        results = self.operations[w.op](w.num1, w.num2)
        d = defer.Deferred()
        reactor.callLater(0, d.callback, results)
        return d

    def ping(self):
        print "ping() called from client"

    def add(self, num1, num2):
        print "add(num1, num2) called from client"
        return num1 + num2

    def calculate(self, logid, w):
        print "calculate(logid, w) called from client"
        try:
            return self._dispatchWork(w)
        except Exception, e:
            return defer.fail(InvalidOperation(what=logid, why=e.message))
            
    def zip(self):
        print "zip() called from client"


if __name__ == '__main__':
    import sys
    if len(sys.argv) != 2:
        print "%s port" % sys.argv[0]
        sys.exit(1)

    port = int(sys.argv[1])

    print 'Starting the server...'

    handler = CalculatorHandler()
    processor = tutorial.Calculator.Processor(handler)
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    reactor.listenTCP(port, TTwisted.ThriftServerFactory(processor, pfactory))
    reactor.run()
