#!/usr/bin/env python3

"""Graphical utility to represent typical CoAP interfaces"""

import asyncio
import argparse

from aiocoap.util.cli import AsyncCLIDaemon
from aiocoap import resource
from aiocoap import Context
from aiocoap.resourcedirectory.client.register import Registerer

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import gbulb.gtk

from widgets_common.gobject_resource import *


class Slider(FloatResource, GobjectBacked):
    if_ = 'core.s'
    unit = 'degC' # FIXME that should be somewhere in core

    widget_property = 'value'

    def __init__(self, args):
        self.widget = Gtk.Scale()
        self.widget.props.draw_value = False

        self.backend_widget = self.widget.props.adjustment = Gtk.Adjustment()

        self.backend_widget.props.lower = -10
        self.backend_widget.props.upper = 40
        self.backend_widget.props.value = 20

        super().__init__()

class WindowTitle(StringResource, GobjectBacked):
    if_ = 'core.p'

    widget_property = 'title'

    def __init__(self, window):
        self.backend_widget = self.widget = window

        super().__init__()

class ArgumentParser(argparse.ArgumentParser):
    def __init__(self):
        super().__init__(description=__doc__.split("\n")[0])

        self.add_argument('--anyport', help="Bind to a non-default port (useful for multiple instances on one computer, and in connection with --register-at)", action='store_true')
        self.add_argument('--register', help="Resource directory to register at (uses multicast if not specified)", metavar='RD', nargs='?', action='append')
        self.add_argument('--register-as', help="Endpoint name (or name.domain) to register as at the resource directory (Default: %(default)s)", default='widget', metavar='EP')

async def start_context(site, args):
    if args.anyport:
        ctx = await Context.create_client_context()
        ctx.serversite = site
    else:
        ctx = await Context.create_server_context(site)

    if args.register:
        ep, _, d = args.register_as.partition('.')
        registerer = Registerer(ctx, args.register[0], lt=120, registration_parameters=dict(ep=ep, d=d))

        async def shutdown():
            await registerer.shutdown()
            await ctx.shutdown()

        return shutdown
    else:
        return ctx.shutdown

class WidgetApplication(AsyncCLIDaemon):
    async def start(self):
        p = ArgumentParser()
        args = p.parse_args()

        win = Gtk.Window()
        win.connect("delete-event", lambda *args: self.stop(0))

        site = resource.Site()
        site.add_resource(['.well-known', 'core'], resource.WKCResource(site.get_resources_as_linkheader))
        site.add_resource(['window-title'], WindowTitle(win))

        # temporary show-all
        box = Gtk.VBox()
        win.add(box)

        rgb = RGBLight(None)
        box.add(rgb.widget)
        site.add_resource(['spot'], rgb)

        switch = Switch(None)
        box.add(switch.widget)
        site.add_resource(['switch'], switch)

        bulb = Bulb(None)
        box.add(bulb.widget)
        site.add_resource(['bulb'], bulb)

        slider = Slider(None)
        box.add(slider.widget)
        site.add_resource(['slider'], slider)

        bigbatch = SubsiteBatch(site)
        site.add_resource([], bigbatch)

        win.show_all()

        self.shutdown = await start_context(site, args)

def sync_main():
    asyncio.set_event_loop_policy(gbulb.gtk.GtkEventLoopPolicy())

    # this will not react correctly to ctrl-c yet because of https://github.com/nathan-hoad/gbulb/issues/20
    WidgetApplication.sync_main()

if __name__ == "__main__":
    sync_main()
