#!/usr/bin/env python

# Contributors Listed Below - COPYRIGHT 2015
# [+] International Business Machines Corp.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.

import dbus
import dbus.service
import dbus.exceptions
import dbus.mainloop.glib
import gobject
from OpenBMCMapper import IntrospectionParser, PathTree
import OpenBMCMapper


class MapperNotFoundException(dbus.exceptions.DBusException):
    _dbus_error_name = OpenBMCMapper.MAPPER_NOT_FOUND

    def __init__(self, path):
        super(MapperNotFoundException, self).__init__(
            "path or object not found: %s" % (path))


class ObjectMapper(dbus.service.Object):
    def __init__(self, bus, path,
                 name_match=OpenBMCMapper.org_dot_openbmc_match,
                 intf_match=OpenBMCMapper.org_dot_openbmc_match):
        super(ObjectMapper, self).__init__(bus.dbus, path)
        self.cache = PathTree()
        self.bus = bus
        self.name_match = name_match
        self.intf_match = intf_match
        self.tag_match = OpenBMCMapper.ListMatch(['children', 'interface'])
        self.service = None

        gobject.idle_add(self.discover)
        self.bus.dbus.add_signal_receiver(
            self.bus_handler,
            dbus_interface=
            dbus.BUS_DAEMON_IFACE,
            signal_name='NameOwnerChanged')
        self.bus.dbus.add_signal_receiver(
            self.interfaces_added_handler,
            dbus_interface=
            dbus.BUS_DAEMON_IFACE + '.ObjectManager',
            signal_name='InterfacesAdded',
            sender_keyword='sender')
        self.bus.dbus.add_signal_receiver(
            self.interfaces_removed_handler,
            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
            signal_name='InterfacesRemoved',
            sender_keyword='sender')

    def bus_match(self, name):
        if name == OpenBMCMapper.MAPPER_NAME:
            return False
        return self.name_match(name)

    def discovery_pending(self):
        return not bool(self.service)

    def interfaces_added_handler(self, path, iprops, **kw):
        name = self.bus.get_owned_name(self.bus_match, kw['sender'])
        if self.discovery_pending() or \
                not self.bus_match(name):
            return

        matches = [x for x in iprops.iterkeys() if self.intf_match(x)]
        self.add_interfaces(path, kw['sender'], matches)

    def interfaces_removed_handler(self, path, interfaces, **kw):
        name = self.bus.get_owned_name(self.bus_match, kw['sender'])
        if self.discovery_pending() or \
                not self.bus_match(name):
            return
        item = self.cache[path]
        sender = kw['sender']
        for x in interfaces:
            if self.intf_match(x):
                try:
                    item[sender].remove(x)
                except ValueError:
                    pass

        # remove the owner if there aren't any interfaces left
        if not item[sender]:
            del item[sender]

        # update if interfaces remain
        if item:
            self.cache[path] = item
        # mark for removal if no interfaces remain
        elif self.cache.get_children(path):
            self.cache.demote(path)
        # delete the entire path if everything is gone
        else:
            del self.cache[path]

    def process_new_owner(self, name):
        # unique name
        return self.discover([IntrospectionParser(name,
                             self.bus.dbus,
                             self.tag_match,
                             self.intf_match)])

    def process_old_owner(self, name):
        for x, y in self.cache.dataitems():
            if name not in y:
                continue
            del y[name]
            if y:
                self.cache[x] = y
            elif self.cache.get_children(x):
                self.cache.demote(x)
            else:
                del self.cache[x]

    def bus_handler(self, service, old, new):
        if self.discovery_pending() or \
                not self.bus_match(service):
            return

        if new:
            self.process_new_owner(new)
        if old:
            self.process_old_owner(old)

    def add_interfaces(self, path, owner, interfaces):
        d = self.cache.setdefault(path, {})
        d = d.setdefault(owner, [])
        self.cache[path][owner] = list(set(d + interfaces))

    def add_items(self, owner, bus_items):
        for x, y in bus_items.iteritems():
            self.add_interfaces(x, owner, y['interfaces'])

    def discover(self, owners=None):
        if not owners:
            owners = [IntrospectionParser(x, self.bus.dbus,
                                          self.tag_match,
                                          self.intf_match)
                      for x in self.bus.get_owner_names(self.bus_match)]
        for o in owners:
            self.add_items(o.name, o.introspect())

        if self.discovery_pending():
            print "ObjectMapper discovery complete..."
            self.service = dbus.service.BusName(
                OpenBMCMapper.MAPPER_NAME, self.bus.dbus)

    @dbus.service.method(OpenBMCMapper.MAPPER_IFACE, 's', 'a{sas}')
    def GetObject(self, path):
        o = self.cache.get(path)
        if not o:
            raise MapperNotFoundException(path)
        return o

    @dbus.service.method(OpenBMCMapper.MAPPER_IFACE, 'si', 'as')
    def GetSubTreePaths(self, path, depth):
        try:
            return self.cache.iterkeys(path, depth)
        except KeyError:
            raise MapperNotFoundException(path)

    @dbus.service.method(OpenBMCMapper.MAPPER_IFACE, 'si', 'a{sa{sas}}')
    def GetSubTree(self, path, depth):
        try:
            return {x: y for x, y in self.cache.dataitems(path, depth)}
        except KeyError:
            raise MapperNotFoundException(path)


class BusWrapper:
    def __init__(self, bus):
        self.dbus = bus

    def get_owned_name(self, match, bus):
        for x in self.get_service_names(match):
            if self.dbus.get_name_owner(x) == bus:
                return x

    def get_service_names(self, match):
        # these are well known names
        return [x for x in self.dbus.list_names()
                if match(x)]

    def get_owner_names(self, match):
        # these are unique connection names
        return list(set(
            [self.dbus.get_name_owner(x)
                for x in self.get_service_names(match)]))

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    bus = dbus.SystemBus()
    o = ObjectMapper(BusWrapper(bus), OpenBMCMapper.MAPPER_PATH)
    loop = gobject.MainLoop()

    loop.run()
