# Contributors Listed Below - COPYRIGHT 2016
# [+] 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 sys
import dbus
import dbus.mainloop.glib
# TODO: openbmc/openbmc#2994 remove python 2 support
try:  # python 2
    import gobject
except ImportError:  # python 3
    from gi.repository import GObject as gobject
import obmc.mapper


class Wait(object):
    def __init__(self, bus, waitlist, *a, **kw):
        self.bus = bus
        self.waitlist = dict(list(zip(waitlist, [None] * len(waitlist))))
        mapper = bus.get_object(
            obmc.mapper.MAPPER_NAME,
            obmc.mapper.MAPPER_PATH,
            introspect=False)
        self.iface = dbus.Interface(
            mapper, dbus_interface=obmc.mapper.MAPPER_IFACE)
        self.done = False
        self.callback = kw.pop('callback', None)
        self.error_callback = kw.pop('error_callback', self.default_error)
        self.busy_retries = kw.pop('busy_retries', 20)
        self.busy_retry_delay_milliseconds = kw.pop(
            'busy_retry_delay_milliseconds', 500)
        self.waitlist_keyword = kw.pop('waitlist_keyword', None)

        self.bus.add_signal_receiver(
            self.introspection_handler,
            dbus_interface=obmc.mapper.MAPPER_IFACE + '.Private',
            signal_name='IntrospectionComplete')
        self.bus.add_signal_receiver(
            self.introspection_handler,
            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager')

        self.introspection_handler()

    @staticmethod
    def default_error(e):
        raise e

    def force_done(self):
        if self.done:
            return

        self.done = True
        self.bus.remove_signal_receiver(
            self.introspection_handler,
            dbus_interface=obmc.mapper.MAPPER_IFACE + '.Private',
            signal_name='IntrospectionComplete')
        self.bus.remove_signal_receiver(
            self.introspection_handler,
            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
            signal_name='InterfacesAdded')

    def check_done(self):
        if not all(self.waitlist.values()) or self.done:
            return

        self.force_done()

        if self.callback:
            kwargs = {}
            if self.waitlist_keyword:
                kwargs[waitlist_keyword] = self.waitlist
            self.callback(**kwargs)

    def get_object_async(self, path, retry):
        method = getattr(self.iface, 'GetObject')
        method.call_async(
            path,
            [],
            signature='sas',
            reply_handler=lambda x: self.get_object_callback(
                path, x),
            error_handler=lambda x: self.get_object_error(
                path, retry, x))
        return False

    def get_object_error(self, path, retry, e):
        if self.done:
            return

        if e.get_dbus_name() == 'org.freedesktop.DBus.Error.FileNotFound':
            pass
        elif e.get_dbus_name() in \
            ['org.freedesktop.DBus.Error.ObjectPathInUse',
             'org.freedesktop.DBus.Error.LimitsExceeded']:
            if retry > self.busy_retries:
                self.force_done()
                self.error_callback(e)
            else:
                gobject.timeout_add(
                    self.busy_retry_delay_milliseconds,
                    self.get_object_async,
                    path,
                    retry + 1)
        else:
            self.force_done()
            self.error_callback(e)

    def get_object_callback(self, path, info):
        self.waitlist[path] = list(info)[0]
        self.check_done()

    def introspection_handler(self, *a, **kw):
        if self.done:
            return

        for path in [
                x for x in list(self.waitlist.keys()) if not self.waitlist[x]]:
            self.get_object_async(path, 0)
