#!/usr/bin/python

from optparse import OptionParser
import os
import re
import sys

from ddm import DataModel
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import gtk
import base64

DBusGMainLoop(set_as_default=True)
    
def on_ready():
    print "Ready"

    ## Queries are called here for the side effect of getting them in DataModel so
    ## they will be in the tree view. Eventually we should make the query something
    ## you can put in the UI or at least on the command line.
    
    
    query = model.query_resource(model.self_resource.resource_id,
                                 "+;contacts [+;aimBuddies [+;icon]];userContacts +;contacters +;lovedAccounts +;topApplications+;pinnedApplications+;email;aim")
    query.execute()

    query = model.query_resource("online-desktop:/o/global", "+;aimBuddies [+;icon]")
    query.execute()

def image_from_data_url(url):
    ## data:image/png;base64,BASE64DATA

    i = url.find('base64,')
    if i < 0:
        return None

    decoded = base64.b64decode(url[i+len('base64,'):])

    loader = gtk.gdk.PixbufLoader()
    loader.write(decoded)
    loader.close()

    pixbuf = loader.get_pixbuf()
    if pixbuf:
        return pixbuf.scale_simple(32, 32, gtk.gdk.INTERP_BILINEAR)
    else:
        return None

class Tree:

    def __init__(self, ddm_model):
        self.__ddm_model = ddm_model
        self.__ddm_model.add_added_handler(self.__resource_added)

        ## model columns are
        ## 0 = resource ID if depth 0
        ## 1 = property name if depth 1
        ## 2 = property namespace
        ## 3 = property value
        ## 4 = pixbuf property value
        self.__store = gtk.TreeStore(str, str, str, str, gtk.gdk.Pixbuf)

        self.__view = gtk.TreeView(self.__store)
        self.__view.set_headers_clickable(True)

        column = gtk.TreeViewColumn('Resource')

        renderer = gtk.CellRendererText()
        column.pack_start(renderer)
        column.set_attributes(renderer, text=0)
        column.set_sort_column_id(0) ## which column in the model is used to sort this display column
        column.set_resizable(True)
        self.__view.append_column(column)

        column = gtk.TreeViewColumn('Property')

        renderer = gtk.CellRendererText()
        column.pack_start(renderer)
        column.set_attributes(renderer, text=1)
        column.set_sort_column_id(1) ## which column in the model is used to sort this display column
        column.set_resizable(True)
        self.__view.append_column(column)

        column = gtk.TreeViewColumn('Property Value')

        renderer = gtk.CellRendererPixbuf()        
        column.pack_start(renderer)
        column.set_attributes(renderer, pixbuf=4)

        renderer = gtk.CellRendererText()        
        column.pack_start(renderer)
        column.set_attributes(renderer, text=3)
        
        column.set_sort_column_id(3) ## which column in the model is used to sort this display column
        column.set_max_width(600)
        column.set_resizable(True)
        self.__view.append_column(column)

    def __on_resource_changed(self, resource):
        found_row = None
        for row in self.__store:
            if row[0] == resource.resource_id:
                found_row = row
                break
        if found_row:
            ## remove the old values
            child = self.__store.iter_children(found_row.iter)
            while child:
                self.__store.remove(child)
                child = self.__store.iter_children(found_row.iter)

            ## add new values
            for (name, value) in resource.get_properties():
                ## hack to see if value is a sequence
                is_sequence = False
                try:
                    foo = value[0:0]
                    is_sequence = True
                except:
                    is_sequence = False

                if isinstance(value, basestring):
                    is_sequence = False
                    
                if is_sequence:
                    ## for lists, make each item in the list a sub-node
                    new_iter = self.__store.append(found_row.iter, [None, name[1], name[0],
                                                                    str(len(value)) + " items", None])
                    for e in value:
                        self.__store.append(new_iter, [None, None, None, e, None])
                else:
                    ## if value is not a list, append the value

                    pixbuf = None
                    if isinstance(value, basestring) and value.startswith("data:"):
                        pixbuf = image_from_data_url(value)
                    
                    self.__store.append(found_row.iter, [None, name[1], name[0], value, pixbuf])

    def __resource_added(self, resource):
        description = resource.resource_id #+ " is a " + resource.class_id
        self.__store.append(None, [ description, None, None, None, None ] )
        resource.connect(self.__on_resource_changed, property=None)
        self.__on_resource_changed(resource)

    def get_widget(self):
        return self.__view
    

parser = OptionParser()
parser.add_option("-s", "--server", default=None, help="Desktop Data Model server to connect to (default is whichever one is running)")
(options, args) = parser.parse_args()
if len(args) > 0:
    parser.print_usage()
    sys.exit(1)

if options.server == "":
    options.server = None

#print "Using server: " + str(options.server)

model = DataModel(server_name=options.server)
model.add_ready_handler(on_ready)
if model.ready:
    on_ready()

window = gtk.Window()
sw = gtk.ScrolledWindow()
tree = Tree(model)
treeview = tree.get_widget()
treeview.show()
sw.add(treeview)
sw.show()
window.add(sw)
window.set_default_size(800, 700)

window.show()

loop = gobject.MainLoop()
loop.run()
