#
# BitBake XMLRPC Server Interface
#
# Copyright (C) 2006 - 2007  Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008  Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import os
import sys

import hashlib
import time
import inspect
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler

import bb

# This request handler checks if the request has a "Bitbake-token" header
# field (this comes from the client side) and compares it with its internal
# "Bitbake-token" field (this comes from the server). If the two are not
# equal, it is assumed that a client is trying to connect to the server
# while another client is connected to the server. In this case, a 503 error
# ("service unavailable") is returned to the client.
class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
    def __init__(self, request, client_address, server):
        self.server = server
        SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server)

    def do_POST(self):
        try:
            remote_token = self.headers["Bitbake-token"]
        except:
            remote_token = None
        if 0 and remote_token != self.server.connection_token and remote_token != "observer":
            self.report_503()
        else:
            if remote_token == "observer":
                self.server.readonly = True
            else:
                self.server.readonly = False
            SimpleXMLRPCRequestHandler.do_POST(self)

    def report_503(self):
        self.send_response(503)
        response = 'No more client allowed'
        self.send_header("Content-type", "text/plain")
        self.send_header("Content-length", str(len(response)))
        self.end_headers()
        self.wfile.write(bytes(response, 'utf-8'))

class BitBakeXMLRPCServer(SimpleXMLRPCServer):
    # remove this when you're done with debugging
    # allow_reuse_address = True

    def __init__(self, interface, cooker, parent):
        # Use auto port configuration
        if (interface[1] == -1):
            interface = (interface[0], 0)
        SimpleXMLRPCServer.__init__(self, interface,
                                    requestHandler=BitBakeXMLRPCRequestHandler,
                                    logRequests=False, allow_none=True)
        self.host, self.port = self.socket.getsockname()
        self.interface = interface

        self.connection_token = None
        self.commands = BitBakeXMLRPCServerCommands(self)
        self.register_functions(self.commands, "")

        self.cooker = cooker
        self.parent = parent


    def register_functions(self, context, prefix):
        """
        Convenience method for registering all functions in the scope
        of this class that start with a common prefix
        """
        methodlist = inspect.getmembers(context, inspect.ismethod)
        for name, method in methodlist:
            if name.startswith(prefix):
                self.register_function(method, name[len(prefix):])

    def get_timeout(self, delay):
        socktimeout = self.socket.gettimeout() or delay
        return min(socktimeout, delay)

    def handle_requests(self):
        self._handle_request_noblock()

class BitBakeXMLRPCServerCommands():

    def __init__(self, server):
        self.server = server
        self.has_client = False

    def registerEventHandler(self, host, port):
        """
        Register a remote UI Event Handler
        """
        s, t = bb.server.xmlrpcclient._create_server(host, port)

        # we don't allow connections if the cooker is running
        if (self.server.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
            return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.server.cooker.state)

        self.event_handle = bb.event.register_UIHhandler(s, True)
        return self.event_handle, 'OK'

    def unregisterEventHandler(self, handlerNum):
        """
        Unregister a remote UI Event Handler
        """
        ret = bb.event.unregister_UIHhandler(handlerNum, True)
        self.event_handle = None
        return ret

    def runCommand(self, command):
        """
        Run a cooker command on the server
        """
        return self.server.cooker.command.runCommand(command, self.server.readonly)

    def getEventHandle(self):
        return self.event_handle

    def terminateServer(self):
        """
        Trigger the server to quit
        """
        self.server.parent.quit = True
        print("XMLRPC Server triggering exit")
        return

    def addClient(self):
        if self.server.parent.haveui:
            return None
        token = hashlib.md5(str(time.time()).encode("utf-8")).hexdigest()
        self.server.connection_token = token
        self.server.parent.haveui = True
        return token

    def removeClient(self):
        if self.server.parent.haveui:
            self.server.connection_token = None
            self.server.parent.haveui = False

