# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import dbus
import dbus.mainloop.glib
import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros import dbus_util

Service = collections.namedtuple('Service', ['service_id', 'service_info'])
Peer = collections.namedtuple('Peer', ['uuid', 'name', 'note',
                                       'last_seen', 'services'])

# DBus constants for use with peerd.
SERVICE_NAME = 'org.chromium.peerd'
DBUS_INTERFACE_MANAGER = 'org.chromium.peerd.Manager'
DBUS_INTERFACE_PEER = 'org.chromium.peerd.Peer'
DBUS_INTERFACE_SERVICE = 'org.chromium.peerd.Service'
DBUS_INTERFACE_OBJECT_MANAGER = 'org.freedesktop.DBus.ObjectManager'
DBUS_PATH_MANAGER = '/org/chromium/peerd/Manager'
DBUS_PATH_OBJECT_MANAGER = '/org/chromium/peerd'
PEER_PATH_PREFIX = '/org/chromium/peerd/peers/'
PEER_PROPERTY_ID = 'UUID'
PEER_PROPERTY_NAME = 'FriendlyName'
PEER_PROPERTY_NOTE = 'Note'
PEER_PROPERTY_LAST_SEEN = 'LastSeen'
SERVICE_PROPERTY_ID = 'ServiceId'
SERVICE_PROPERTY_INFO = 'ServiceInfo'

# Possible technologies for use with PeerdHelper.start_monitoring().
TECHNOLOGY_ALL = dbus.UInt32(1 << 0)
TECHNOLOGY_MDNS = dbus.UInt32(1 << 1)


def make_helper(bus=None, timeout_seconds=10, verbosity_level=0):
    """Wait for peerd to come up, then return a PeerdHelper for it.

    @param bus: DBus bus to use, or specify None to create one internally.
    @param timeout_seconds: number of seconds to wait for peerd to come up.
    @param verbosity_level: int level of log verbosity from peerd (e.g. 0
                            will log INFO level, 3 is verbosity level 3).
    @return PeerdHelper instance if peerd comes up, None otherwise.

    """
    utils.run('stop peerd')
    utils.run('start peerd PEERD_LOG_LEVEL=%d' % verbosity_level)
    if bus is None:
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        bus = dbus.SystemBus()
    end_time = time.time() + timeout_seconds
    connection = None
    while time.time() < end_time:
        if not bus.name_has_owner(SERVICE_NAME):
            time.sleep(0.2)
        return PeerdHelper(bus)
    raise error.TestFail('peerd did not start in a timely manner.')


class PeerdHelper(object):
    """Container for convenience methods related to peerd."""

    def __init__(self, bus):
        """Construct a PeerdHelper.

        @param bus: DBus bus to use, or specify None and this object will
                    create a mainloop and bus.

        """
        self._bus = bus
        self._manager = dbus.Interface(
                self._bus.get_object(SERVICE_NAME, DBUS_PATH_MANAGER),
                DBUS_INTERFACE_MANAGER)


    def _get_peers(self):
        object_manager = dbus.Interface(
                self._bus.get_object(SERVICE_NAME, DBUS_PATH_OBJECT_MANAGER),
                DBUS_INTERFACE_OBJECT_MANAGER)
        # |dbus_objects| is a map<object path,
        #                         map<interface name,
        #                             map<property name, value>>>
        dbus_objects = object_manager.GetManagedObjects()
        objects = dbus_util.dbus2primitive(dbus_objects)
        peer_objects = [(path, interfaces)
                        for path, interfaces in objects.iteritems()
                        if (path.startswith(PEER_PATH_PREFIX) and
                            DBUS_INTERFACE_PEER in interfaces)]
        peers = []
        for peer_path, interfaces in peer_objects:
            service_property_sets = [
                    interfaces[DBUS_INTERFACE_SERVICE]
                    for path, interfaces in objects.iteritems()
                    if (path.startswith(peer_path + '/services/') and
                        DBUS_INTERFACE_SERVICE in interfaces)]
            services = []
            for service_properties in service_property_sets:
                services.append(Service(
                        service_id=service_properties[SERVICE_PROPERTY_ID],
                        service_info=service_properties[SERVICE_PROPERTY_INFO]))
            peer_properties = interfaces[DBUS_INTERFACE_PEER]
            peer = Peer(uuid=peer_properties[PEER_PROPERTY_ID],
                        name=peer_properties[PEER_PROPERTY_NAME],
                        note=peer_properties[PEER_PROPERTY_NOTE],
                        last_seen=peer_properties[PEER_PROPERTY_LAST_SEEN],
                        services=services)
            peers.append(peer)
        return peers


    def close(self):
        """Clean up peerd state related to this helper."""
        utils.run('stop peerd')
        utils.run('start peerd')


    def start_monitoring(self, technologies):
        """Monitor the specified technologies.

        Note that peerd will watch bus connections and stop monitoring a
        technology if this bus connection goes away.A

        @param technologies: iterable container of TECHNOLOGY_* defined above.
        @return string monitoring_token for use with stop_monitoring().

        """
        return self._manager.StartMonitoring(technologies)


    def has_peer(self, uuid, name=None, note=None):
        """
        Return a Peer instance if peerd has found a matching peer.

        Optional parameters are also matched if not None.

        @param uuid: string unique identifier of peer.
        @param name: string optional friendly name of peer.
        @param note: string optional note of peer.
        @return Peer tuple if a matching peer exists, None otherwise.

        """
        peers = self._get_peers()
        logging.debug('Found peers: %r.', peers)
        for peer in peers:
            if peer.uuid != uuid:
                continue
            if name is not None and name != peer.name:
                logging.debug('Mismatched peer names; found %s, expected %s.',
                              peer.name, name)
                return None
            if note is not None and note != peer.note:
                logging.debug('Mismatched peer notes; found %s, expected %s.',
                              peer.note, note)
                return None
            return peer
        logging.debug('No peer had a matching ID.')
        return None


    def expose_service(self, service_id, service_info):
        """Expose a service via peerd.

        Note that peerd should watch DBus connections and remove this service
        if our bus connection ever goes down.

        @param service_id: string id of service.  See peerd documentation
                           for limitations on this string.
        @param service_info: dict of string, string entries.  See peerd
                             documentation for relevant restrictions.
        @return string service token for use with remove_service().

        """
        return self._manager.ExposeService(service_id, service_info)


    def remove_service(self, service_token):
        """Remove a service previously added via expose_service().

        @param service_token: string token returned by expose_service().

        """
        self._manager.RemoveExposedService(service_token)
