import ConfigParser, os
import dircache
import dbus

"""
The registry of managers takes the form of any number of .manager files, which
are searched for in /usr/share/telepathy/services or in ~/.telepathy.

.manager files should have an initial stanza of the form:

[ConnectionManager]
Name = value
ServiceName = value
ManagerObject = value


where:
'Name' field sets the name of connection manager.
'ServiceName' sets the DBus bus name of this connetion manager.
'ManagerObject' sets the Dbus object path to the ConnectionManager object under this service.

Then any number of proctol support declarators of the form:

[Proto (name of supported protocol)]
MandatoryParams = list of values
OptionalParams = list of values
default-(paramater name) = value

Where:
MandatoryParams is a comma-seperated list of mandatory parameters that must be passed to Connections created by this ConnectionManager for this protocol. Each should be of the form dbus type signature:name, eg s:password, indicating a paramater called 'password' of type string.
OptionalParams is a comma-separated list of optional params, of same form as MandatoryParams.
default-(paramater name) sets the default value for that parameter. e.g. default-port=522 sets te default value of the 'port' parameter to 522.
 
All connection managers should register as activatable dbus services. They should also close themselves down after an idle time with no open connections.

Clients should use the Proto sections to query the user for necessary informatoin.

Telepathy defines a common subset of paramter names to facilitate GUI design.

server - a fully qualified domain name or numeric IPv4 or IPv6 address. Using the fully-qualified domain name form is RECOMMENDED whenever possible. If this paramter is specified and the user id for that service also specifies a server, this parameter should override that in the user id.

port - a TCP or UDP port number. If this paramter is specified and the user id for that service also specifies a port, this parameter should override that in the user id.

password - A password associated with the user. 

proxy-server - a uri for a proxyserver to use for this connection

"""

class ManagerRegistry:
    def __init__(self):
        self.services = {}

    def LoadManagers(self):
        """
        Searches local and system wide configurations
    
        Can raise all ConfigParser errors. Generally filename member will be
        set to the name of the erronous file.
        """
        config = ConfigParser.SafeConfigParser()
        all_services=[]
        if os.path.exists("/usr/share/telepathy/services/"):
            all_services += dircache.listdir("/usr/share/telepathy/services/")
        if os.path.exists(os.path.expanduser("~/.telepathy")):
            all_services += dircache.listdir(os.path.expanduser("~/.telepathy"))
        for service in all_services:
            config.read(service)
            connection_manager =dict(config.items("ConnectionManager"))
            if "name" not in connection_manager.keys():
                raise ConfigParser.NoOptionError("name","ConnectionManager")
            self.services[connection_manager["name"]]=connection_manager
            for section in set(config.sections()) - set(["ConnectionManager"]):
                if section[:6]=="Proto ":
                    self.services[connection_manager["name"]]["protos"]={section[6:]:dict(config.items(section))}
                

    def GetProtos(self):
        """
        returns a list of protocols supported on this system
        """
        protos=[]
        for service in self.services.keys():
            if self.services[service].has_key("protos"):
                protos.extend(self.services[service]["protos"].keys())
        return protos
       
    def GetManagers(self, proto):
        """
        Returns names of managers that can handle the given protocol.
        """
        managers = []
        for service in self.services.keys():
            if self.services[service].has_key("protos"):
                if self.services[service]["protos"][proto]:
                    managers.append(service)
        return managers
                    
    def GetParams(self, manager, proto):
        """
        Returns two dicts of paramters for the given proto on the given manager.
        One dict of mandatory parameters, one of optional.
        The keys will be the parameters names, and the values a tuple of 
        (dbus type, default value). If no default value is specified, the second
        item in the tuple will be None.
        """
        ret=()
       
        for field in ["MandatoryParams","OptionalParams"]:
            params={}
            for item in split(self.services[manager][proto][field],','):
                type, name = split(strip(item),':')
                default=None
                for key in self.services[manager][proto].keys():
                    strip(key)
                    if key=="Default-"+name:
                        default=key[8:]
                        break
                if default:
                    params[name]=(type, dbus.Variant(default,signature=type))
                else:
                    params[name]=(type, None)
            ret.append(params)
        
        return ret


@@ -1593,16 +1593,18 @@
 esign.%0A%0A
+s:
 server -
@@ -1885,16 +1885,18 @@
 er id.%0A%0A
+q:
 port - a
@@ -2059,16 +2059,18 @@
 er id.%0A%0A
+s:
 password
@@ -2111,16 +2111,18 @@
 user. %0A%0A
+s:
 proxy-se
@@ -2180,16 +2180,235 @@
 ection%0A%0A
+b:require-encryption - require encryption for this connection. A connection %0Ashould fail if require-encryption is set and encryption is not possible.%0A%0AUIs should display any default values, but should *not* store them.%0A
 %22%22%22%0A%0Acla

define some common connection parameter types