#!/usr/bin/python

from common import modules
from common import prototypes
from common import xmlrpc
from common import exception

import config
import logging

# Port the client listens on
port = 5740
serverPort = 5741

# Logger
log = logging.getLogger()

class ClientServerAPI(object):

    def __init__(self, cfg):
        self.cfg = cfg
        self.client = None      # pointer to Client object


    def getUID(self):
        return self.cfg.getUID()
    

    def register(self, uuid):
        """Server may call this function to register this client when
           this client has not been registered before."""

        if self.cfg.getUID() == "":
            self.cfg.setUID(uuid)
        else:
            log.error("Server tried to reset UUID!")
            return (1, {})
       
        return (0, {})
    
        
    def runAction(self, actionID, args, kwargs):
        return self.client.kickAction(actionID, args, kwargs)


class Client(object):
    
    def __init__(self, cfg):
        self.cfg = cfg

    
    def doRegister(self, server):
        ret = server.register()

        if ret[0] > 0:
            log.error("Registration with server failed.  Code: %s" % ret[0])
            log.error("Error: %s" % ret[1]['error'])
            raise exception.ClientError("Registration Failed")

        self.cfg.setUID(ret[1]['uid'])
        return ret[1]['uid']

    
    def pollServer(self):
        url = "http://%s:%s" % (self.cfg.getServer(), serverPort)
        server = xmlrpc.ServerProxy(url,
                                    self.cfg.getCert(),
                                    self.cfg.getCA(),
                                    self.cfg.getPeer())
        
        uuid = self.cfg.getUID()
        if uuid == "":
            uuid = self.doRegister(server)

        ret = server.login(uuid)
        if ret[0] > 0:
            raise exception.ClientError("Login Failed")

        sid = ret[1]['session']

        ret = server.get(sid)
        while ret[0] == 0 and ret[1].has_key("action"):
            action = ret[1]['action']
            # action == (ID, name, args, kwargs

            ret = self.kickAction(action[1], action[2], action[3])
            # XXX: Figure out what to submit from the return
            if ret[0] > 0:
                log.warning("Action Failed: %s" % action[1])
            else:
                log.info("Action was successful")

            ret = server.get(sid)

        log.info("Finished polling server.")


    def kickAction(self, actionID, args, kwargs):
        log.info("Trying to run action: %s" % actionID)
        m = modules.getClass("actions/", prototypes.Action, actionID)

        instance = m(*args, **kwargs)
        return instance._run()
        
    
    def runServer(self):
        # Run the client XMLRPC interface
        # client is a clientServer object
    
        self.clientapi = ClientServerAPI(self.cfg)
        self.clientapi.client = self
        
        testServer = xmlrpc.Server("", port,
                                   self.cfg.getCert(),
                                   self.cfg.getCA(),
                                   self.cfg.getPeer())

        testServer.register_instance(self.clientapi)

        try:
            testServer.serve_forever()
        except Exception, e:
            log.warning("Received " + str(e))
        
        log.info("Shutting down client...")
        

def startClient(poll=False):
    cfg = config.Client()
    client = Client(cfg)

    if poll:
        client.pollServer()
    else:
        client.runServer()
        


