import e32
import appuifw

import socket
import inbox
import messaging

colours = { 'aliceblue': 'F0F8FF', 'antiquewhite': 'FAEBD7', 'aqua':
'00FFFF', 'aquamarine': '7FFFD4', 'azure': 'F0FFFF', 'beige': 'F5F5DC',
'bisque': 'FFE4C4', 'black': '000000', 'blanchedalmond': 'FFEBCD',
'blue': '0000FF', 'blueviolet': '8A2BE2', 'brown': 'A52A2A',
'burlywood': 'DEB887', 'cadetblue': '5F9EA0', 'chartreuse': '7FFF00',
'chocolate': 'D2691E', 'coral': 'FF7F50', 'cornflowerblue': '6495ED',
'cornsilk': 'FFF8DC', 'crimson': 'DC143C', 'cyan': '00FFFF', 'darkblue':
'00008B', 'darkcyan': '008B8B', 'darkgoldenr0d': 'B8860B', 'darkgray':
'A9A9A9', 'darkgreen': '006400', 'darkkhaki': 'BDB76B', 'darkmagenta':
'8B008B', 'darkolivegreen': '556B2F', 'darkorange': 'FF8C00',
'darkorchid': '9932CC', 'darkred': '8B0000', 'darksalmon': 'E9967A',
'darkseagreen': '8FBC8F', 'darkslateblue': '483D8B', 'darkslategray':
'2F4F4F', 'darkturquoise': '00CED1', 'darkviolet': '9400D3', 'deeppink':
'FF1493', 'deepskyblue': '00BFFF', 'dimgray': '696969', 'dodgerblue':
'1E90FF', 'firebrick': 'B22222', 'floralwhite': 'FFFAF0', 'forestgreen':
'228B22', 'fuchsia': 'FF00FF', 'gainsboro': 'DCDCDC', 'ghostwhite':
'F8F8FF', 'gold': 'FFD700', 'goldenrod': 'DAA520', 'gray': '808080',
'green': '008000', 'greenyellow': 'ADFF2F', 'honeydew': 'F0FFF0',
'hotpink': 'FF69B4', 'indianred': 'CD5C5C', 'indigo': '4B0082', 'ivory':
'FFFFF0', 'khaki': 'F0E68C', 'lavender': 'E6E6FA', 'lavenderblush':
'FFF0F5', 'lawngreen': '7CFC00', 'lemonchiffon': 'FFFACD', 'lightblue':
'ADD8E6', 'lightcoral': 'F08080', 'lightcyan': 'E0FFFF',
'lightgoldenrodyellow': 'FAFAD2', 'lightgreen': '90EE90', 'lightgrey':
'D3D3D3', 'lightpink': 'FFB6C1', 'lightsalmon': 'FFA07A',
'lightseagreen': '20B2AA', 'lightskyblue': '87CEFA', 'lightslategray':
'778899', 'lightsteelblue': 'B0C4DE', 'lightyellow': 'FFFFE0', 'lime':
'00FF00', 'limegreen': '32CD32', 'linen': 'FAF0E6', 'magenta': 'FF00FF',
'maroon': '800000', 'mediumaquamarine': '66CDAA', 'mediumblue':
'0000CD', 'mediumorchid': 'BA55D3', 'mediumpurple': '9370DB',
'mediumseagreen': '3CB371', 'mediumslateblue': '7B68EE',
'mediumspringgreen': '00FA9A', 'mediumturquoise': '48D1CC',
'mediumvioletred': 'C71585', 'midnightblue': '191970', 'mintcream':
'F5FFFA', 'mistyrose': 'FFE4E1', 'moccasin': 'FFE4B5', 'navajowhite':
'FFDEAD', 'navy': '000080', 'oldlace': 'FDF5E6', 'olive': '808000',
'olivedrab': '6B8E23', 'orange': 'FFA500', 'orangered': 'FF4500',
'orchid': 'DA70D6', 'palegoldenrod': 'EEE8AA', 'palegreen': '98FB98',
'paleturquoise': 'AFEEEE', 'palevioletred': 'DB7093', 'papayawhip':
'FFEFD5', 'peachpuff': 'FFDAB9', 'peru': 'CD853F', 'pink': 'FFC0CB',
'plum': 'DDA0DD', 'powderblue': 'B0E0E6', 'purple': '800080', 'red':
'FF0000', 'rosybrown': 'BC8F8F', 'royalblue': '4169E1', 'saddlebrown':
'8B4513', 'salmon': 'FA8072', 'sandybrown': 'F4A460', 'seagreen':
'2E8B57', 'seashell': 'FFF5EE', 'sienna': 'A0522D', 'silver': 'C0C0C0',
'skyblue': '87CEEB', 'slateblue': '6A5ACD', 'slategray': '708090',
'snow': 'FFFAFA', 'springgreen': '00FF7F', 'steelblue': '4682B4', 'tan':
'D2B48C', 'teal': '008080', 'thistle': 'D8BFD8', 'tomato': 'FF6347',
'turquoise': '40E0D0', 'violet': 'EE82EE', 'wheat': 'F5DEB3', 'white':
'FFFFFF', 'whitesmoke': 'F5F5F5', 'yellow': 'FFFF00', 'yellowgreen':
'9ACD32' }

# socket set up
def connect(address=None):
    """Form an RFCOMM socket connection to the given address. If
    address is not given or None, query the user where to connect. The
    user is given an option to save the discovered host address and
    port to a configuration file so that connection can be done
    without discovery in the future.

    Return value: opened Bluetooth socket or None if the user cancels
    the connection.
    """
    
    # Bluetooth connection
    sock=socket.socket(socket.AF_BT,socket.SOCK_STREAM)

    if not address:
        print "Discovering..."
        try:
            addr,services=socket.bt_discover()
        except socket.error, err:
            if err[0]==2: # "no such file or directory"
                appuifw.note(u'No serial ports found.','error')
            elif err[0]==4: # "interrupted system call"
                print "Cancelled by user."
            elif err[0]==13: # "permission denied"
                print "Discovery failed: permission denied."
            else:
                raise
            return None
        print "Discovered: %s, %s"%(addr,services)
        if len(services)>1:
            import appuifw
            choices=services.keys()
            choices.sort()
            choice=appuifw.popup_menu([unicode(services[x])+": "+x
                                       for x in choices],u'Choose port:')
            port=services[choices[choice]]
        else:
            port=services[services.keys()[0]]
        address=(addr,port)
                
    print "Connecting to "+str(address)+"...",
    try:
        sock.connect(address)
    except socket.error, err:
        if err[0]==54: # "connection refused"
            appuifw.note(u'Connection refused.','error')
            return None
        raise
    print "OK."
    print "Ready to receive messages"
    return sock

def quit():
    global sock
    global running
    if sock: sock.close()
    running = 0

def run():
    global sock
    global running
    sock=None
    running = 1
    try:            
        sock=connect()
        if sock is None:
            print "Connection failed."
            return
        sock.send('\r\nConnected.\r\n')
        try:
           i = inbox.Inbox()
           i.bind(scan_for_colours)
           while running:
               e32.ao_yield()
        except IOError, e:
            print "Disconnected: %s"%e                
    finally:
        if sock: sock.close()

def scan_for_colours(msg_id):
    print "Received message ID %s" % msg_id
    i=inbox.Inbox() 
    content = i.content(msg_id)
    address = i.address(msg_id)
    print "From: %s\nMessage: %s" % (address, content)
    words = content.split(" ")
    if words[0].lower() != 'badge'    :
        print "Ignored message!"
    else:
        error = True
        colour_name = words[1].lower()
        if colours.has_key(colour_name):
            hex = '#%s' % colours[colour_name]
            print "OK from names! %s = %s" % (colour_name, hex)
            error = False
        if colour_name[0] == '#' and is_hex(colour_name):
            hex = colour_name
            print "OK from hex! Using %s " % hex
            error = False
            
        # annoyingly, address could just be a name if it's someone in our address book
        # check that it is a number before we send a response via text
        if address[0] not in "+0123456789":
            address = False
            
        if error:
            print "There is no such colour as %s!" % colour_name
            if address:
                messaging.sms_send(address, "Sorry. Tristan's name badge doesn't know a colour called '%s'. Check the list at http://tinyurl.com/2m5vob" % colour_name )
        else:
            sock.send('%s\n' % hex)
            if address:
                messaging.sms_send(address, "Thanks for your command. Tristan's name badge has now been changed to %s (hex value %s)" % (colour_name, hex) )

def is_hex(string):
    hex_digits = '0123456789ABCDEFabcdef'
    if len(string) != 7:
        return False
    string = string[1:7]
    index = 0
    while index < len(string):
        if not string[index] in hex_digits:
            return False
        index += 1
    return True

def main(names=None):
    if e32.is_ui_thread():
        import appuifw
        old_app_title=appuifw.app.title
        appuifw.app.exit_key_handler = quit
        appuifw.app.title=u'SMS colour reader'
    try:
        run()
    finally:
        if e32.is_ui_thread():
            appuifw.app.title=old_app_title
    print "Done."

if __name__ == "__main__":
    main()


    