@external
class WebSocket:
    pass


class Client:
    auto_dispatch = False

    def __init__(self):
        ws = WebSocket('ws://' + window.location.host + '/messages/')
        # Instead of explicitly binding the callback methods to self, we could
        # also have used `from __python__ import bound_methods`.
        ws.onopen = self.on_open.bind(self)
        ws.onclose = self.on_close.bind(self)
        ws.onmessage = self._on_message.bind(self)

    def start(self):
        print('Starting...')
        fetch('/start/')

    def stop(self):
        print('Stopping...')
        fetch('/stop/')

    def on_open(self, evt):
        self.start()

    def on_close(self, evt):
        pass

    def _on_message(self, evt):
        obj = JSON.parse(evt.data)
        if self.auto_dispatch:
            method = getattr(self, 'on_' + obj['type'], None)
            if method is None:
                print(obj)
            else:
                method(obj)
        else:
            self.on_object(obj)

    def on_object(self, obj):
        raise NotImplementedError()
