#! /usr/bin/env python

from gi.repository import GLib
import pydbus
import coiot.dbus
from coiot.device import CoiotDevice
from coiot.device_action_list import DeviceActionList
from coiot.db import CoiotDB, CoiotDBInterface
import logging
import sys
import argparse

log = logging.getLogger('coiotd')

if __name__ == "__main__":
    ap = argparse.ArgumentParser(description='COIoT devices control daemon')
    ap.add_argument('-d', '--db', default='/tmp/coiot.db',
                    help='database file')
    ap.add_argument('-v', '--verbose', action='store_true', default=False,
                    help='verbose logs')
    ap.add_argument('--mock', action='store_true', default=False,
                    help='Mock drivers instead of using the real drivers.')

    args = ap.parse_args()

    for logn in 'DB', 'DBus', 'Device', 'BLE', 'Test', 'SONOS':
        log = logging.getLogger(logn)
        bf = logging.Formatter('{asctime} {name:8s} {levelname:8s} {message}',
                               style='{')
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(bf)
        log.addHandler(handler)
        if args.verbose:
            log.level = logging.DEBUG
        else:
            log.level = logging.WARNING

    updates = DeviceActionList()
    if args.mock:
        from test.mock_driver import MockDeviceDriver
        MockDeviceDriver.register()
        MockDeviceDriver.driver.set = updates.set
    else:
        import ble.bluez
        import ble.driver
        import driver.player.sonos

        drivers = set()

        adapter = ble.bluez.DBusBluez().adapters['hci0']
        drivers.add(ble.driver.BluezBLEDriver(adapter, updates))

        drivers.add(driver.player.sonos.SonosDriver(updates))

    db = CoiotDB(args.db)
    devices = CoiotDevice.load(db)

    for i in CoiotDBInterface.interfaces:
        if hasattr(i, "autodetect"):
            d = i.autodetect()
            if d:
                log.info("install {} for {}".format(i.__name__, d))
                new = db.install()
                if hasattr(d, 'keys') and hasattr(d, '__getitem__'):
                    i.install(new, **d)
                elif hasattr(d, '__iter__'):
                    i.install(new, *d)
                else:
                    i.install(new, d)

    def idle_push_updates():
        while updates:
            d, k, v = updates.pop()
            d.update(k, v)
            log.debug('updated {}.{} = {}'.format(d.ID, k, v))
        return True

    bus = coiot.dbus.CoiotDBus(pydbus.SystemBus())
    for device in devices:
        coiot.dbus.DBusDevice(bus, device)

    loop = GLib.MainLoop()
    GLib.timeout_add(100, idle_push_updates)
    try:
        loop.run()
    finally:
        if not args.mock:
            for d in drivers:
                d.stop()
