import sys, string, types
from Ft.Server.Server import FTSERVER_SERVER_NS, Module, ServerConfig

# needed for CoreModule.setLogLevel
from Lib import LogUtil

class CoreModule(Module):

    # A mapping of expanded names to handling function names
    # The value can be None, a single name or a pair of names:
    #  None   - tag is OK in file, but nothing is done
    #  single - function is called after the element's end tag is reached
    #  pair   - first function is called when tag is started, second is same as single

    commands = {
        (FTSERVER_SERVER_NS, 'Server') : 'finalizeServer',
        (FTSERVER_SERVER_NS, 'Module') : 'addModule',
        (FTSERVER_SERVER_NS, 'Handler') : 'setHandler',
        (FTSERVER_SERVER_NS, 'Ident') : 'setIdent',
        (FTSERVER_SERVER_NS, 'ServerAdmin') : 'setServerAdmin',
        (FTSERVER_SERVER_NS, 'SessionTTL') : 'setSessionTTL',
        (FTSERVER_SERVER_NS, 'ServerName') : 'setServerName',
        (FTSERVER_SERVER_NS, 'ServerAlias') : 'addServerAlias',
        (FTSERVER_SERVER_NS, 'Port') : 'setPort',
        (FTSERVER_SERVER_NS, 'Status') : None,
        (FTSERVER_SERVER_NS, 'LogLevel') : 'setLogLevel',
        (FTSERVER_SERVER_NS, 'VirtualHost') : ('startVhost', 'endVhost'),
        }

    # Function arguments:
    #  parser - the ConfigParser instance
    #  config - the ServerConfig instance
    #  name   - the localName of element being handled
    #  data   - for first function it is the attributes dictionary (from expat)
    #           for single and second functions, it is the text content of the
    #             the element with leading and trailing WS removed

    def finalizeServer(self, parser, config, name, data,attrs):
        # Here is where conversion of values should be performed
        # and other per server configuration details
        return

    def addModule(self, parser, config, name, data,attrs):
        if '.' not in data:
            # A Fourthought provided module
            # This disallows anything toplevel, but I think that is
            # OK due to the ease of use for users
            if _ft_builtins.has_key(data):
                object = _ft_builtins[data]
            else:
                raise Exception("Cannot load '" + data + "' into server: "
                                "not in list of builtins")
        else:
            object = self.loadObject(data)
        try:
            parser.addModule(object)
        except Exception, exc:
            raise Exception("Cannot load '%s' into server: %s" % (data,
                                                                  str(exc)))
        return

    def setHandler(self, parser, config, name, data,attrs):
        handler = parser.findHandler(data)
        config.handler = handler
        return

    def setIdent(self, parser, config, name, data, attrs):
        config.ident = data
        return

    def setPort(self, parser, config, name, data, attrs):
        try:
            config.port = int(data)
        except ValueError:
            raise Exception('%s must be numeric' % name)
        return

    def setServerAdmin(self, parser, config, name, data,attrs):
        config.admin = data
        return

    def setSessionTTL(self, parser, config, name, data,attrs):
        try:
	    config.session_ttl = int(data)
        except ValueError:
            raise Exception('SessionTTL must be numeric; %s given' % name)
        return

    def setServerName(self, parser, config, name, data,attrs):
        config.hostname = data.lower()
        config.names.append(data.lower())
        return

    def addServerAlias(self, parser, config, name, data,attrs):
        config.names.append(data.lower())
        return

    def setLogLevel(self, parser, config, name, data,attrs):
        if not data:
            raise Exception('%s requires level keyword' % name)
        
        try:
            config.logLevel = LogUtil.FromString(data)
        except ValueError, error:
            raise Exception('%s requires level keyword: %s' %
                            (name, str(error)))
        return

    def setErrorLog(self, parser, config, name, data,attrs):
        config.errorFilename = data
        return

    # -- virtual hosts -----------------------------------------------

    def startVhost(self, parser, config, name, attrs):
        if config.isVirtual:
            raise Exception('%s cannot be nested' % name)
        virtual = ServerConfig.ServerConfig(config.path, 1)
        self._main_server = config
        parser.config = virtual
        config.virtualHosts.append(virtual)
        return

    def endVhost(self, parser, config, name, data, attrs):
        if config.hostname is None:
            raise Exception('VirtualHost missing required ServerName')
        parser.config = self._main_server
        return



from Http import HttpModule
from FtRpc import FtRpcModule
from Ftp import FtpModule
from Http.Soap import SoapModule

_ft_builtins = {
    'Core' : CoreModule,
    'Http' : HttpModule,
    'FtRpc' : FtRpcModule,
    'Ftp':  FtpModule,
    'Soap': SoapModule,
    }
