#!/usr/bin/python2
from __future__ import absolute_import, print_function, unicode_literals

from gi.repository import GObject

import sys
import dbus
import dbus.service
import dbus.mainloop.glib
from optparse import OptionParser


class Paired:
    pass

def ask(prompt):
    try:
        return raw_input(prompt)
    except:
        return input(prompt)

class Rejected(dbus.DBusException):
    _dbus_error_name = "org.bluez.Error.Rejected"

passkey = '0000'

class Agent(dbus.service.Object):
    exit_on_release = True

    def set_exit_on_release(self, exit_on_release):
        self.exit_on_release = exit_on_release

    @dbus.service.method("org.bluez.Agent",
            in_signature="", out_signature="")
    def Release(self):
        print("Released")
        sys.exit()
        #if self.exit_on_release:

    @dbus.service.method("org.bluez.Agent",
            in_signature="os", out_signature="")
    def Authorize(self, device, uuid):
        print("Authorize (%s, %s)" % (device, uuid))
        authorize = ask("Authorize connection (yes/no): ")
        if (authorize == "yes"):
            return
        raise Rejected("Connection rejected by user")

    @dbus.service.method("org.bluez.Agent",
            in_signature="o", out_signature="s")
    def RequestPinCode(self, device):
        print("RequestPinCode (%s)" % (device))
        global passkey
        return passkey

    @dbus.service.method("org.bluez.Agent",
            in_signature="o", out_signature="u")
    def RequestPasskey(self, device):
        print("RequestPasskey (%s)" % (device))
        global passkey
        return dbus.UInt32(passkey)

    @dbus.service.method("org.bluez.Agent",
            in_signature="ouq", out_signature="")
    def DisplayPasskey(self, device, passkey, entered):
        print("DisplayPasskey (%s, %06u entered %u)" % (device, passkey, entered))

    @dbus.service.method("org.bluez.Agent",
            in_signature="os", out_signature="")
    def DisplayPinCode(self, device, pincode):
        print("DisplayPinCode (%s, %s)" % (device, pincode))

    @dbus.service.method("org.bluez.Agent",
            in_signature="ou", out_signature="")
    def RequestConfirmation(self, device, passkey):
        print("RequestConfirmation (%s, %06d)" % (device, passkey))
        #confirm = ask("Confirm passkey (yes/no): ")
        #if (confirm == "yes"):
        return
        #raise Rejected("Passkey doesn't match")

    @dbus.service.method("org.bluez.Agent",
            in_signature="s", out_signature="")
    def ConfirmModeChange(self, mode):
        print("ConfirmModeChange (%s)" % (mode))
        authorize = ask("Authorize mode change (yes/no): ")
        if (authorize == "yes"):
            return
        raise Rejected("Mode change by user")

    @dbus.service.method("org.bluez.Agent",
            in_signature="", out_signature="")
    def Cancel(self):
        print("Cancel")

def create_device_reply(device):
    print("New device (%s)" % (device))
    sys.exit(1)

def create_device_error(error):
    print("Creating device failed: %s" % (error))
    sys.exit(1)

if __name__ == '__main__':
    #sys.argv = ['bluez-simple-agent',adapt, addr]
    
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()
    manager = dbus.Interface(bus.get_object("org.bluez", "/"),
            "org.bluez.Manager")

    capability = "KeyboardDisplay"

    parser = OptionParser()
    parser.add_option("-c", "--capability", action="store",
            type="string", dest="capability")

    parser.add_option("-p", "--pin", action="store",
            type="string")

    (options, args) = parser.parse_args()

    print(options,args)
    print('running ', sys.argv)
    print(args)
    if options.capability:
        capability  = options.capability

    if len(args) > 0:
        path = manager.FindAdapter(args[0])
    else:
        path = manager.DefaultAdapter()

    print (path)

    adapter = dbus.Interface(bus.get_object("org.bluez", path),
            "org.bluez.Adapter")

    path = "/test/agent"
    agent = Agent(bus, path)

    mainloop = GObject.MainLoop()

    if len(args) > 1:
        try:
            device = adapter.FindDevice(args[1])
            adapter.RemoveDevice(device)
        except: pass
        print (adapter)

        agent.set_exit_on_release(False)
        adapter.CreatePairedDevice(args[1], path, capability,
                timeout=60000,
                reply_handler=create_device_reply,
                error_handler=create_device_error)
    else:
        adapter.RegisterAgent(path, capability)
        print("Agent registered")

    mainloop.run()

    #adapter.UnregisterAgent(path)
    #print("Agent unregistered")
