from system import logger, dataset

import pygtk
import gtk
import gtk.gdk
import gtk.glade
import gnome
import gnome.ui
import gobject

class SimpleMenu(gtk.Menu):
    def __init__(self):
        gtk.Menu.__init__(self)
        
    def add_simple_item(self, title, function):
        item = gtk.MenuItem(title)
        item.connect('activate', function)
        self.append(item)
        item.show()

class SelectionTree(gtk.TreeView):
    
    def __init__(self):
        self.store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
        gtk.TreeView.__init__(self, self.store)

        renderer = gtk.CellRendererText()
        sel_column = gtk.TreeViewColumn('Selection', renderer, text=0)
        self.insert_column(sel_column, 0)

        self.connect('row-activated', self._on_row_activated)
        self.connect('cursor-changed', self._on_cursor_changed)

        self._identifier_list = None
        self._dim_list = {}

        # A mapping of selection names to selection lines.
        self._selections = []

        self.set_headers_visible(True)
        self._current_dim = None
        self._current_selection = None
        
        # Set up context menu
        self._menu = SimpleMenu()
        self._menu.add_simple_item('Select', self._on_set_selection)

        self.connect('popup_menu', self._on_popup_menu)
        self.connect('button_press_event', self._on_button_press_event)

    def set_identifier_list(self, identifier_list):
        """Dependency injection. Sets the widget that should be used to 
           display the selected identifiers."""
        self._identifier_list = identifier_list

    def set_project(self, project):
        """Dependency injection. Set the current project."""
        self.project = project
        project.add_selection_observer(self)
        project.add_dataset_observer(self)
        self.update_dims(project.dim_names)
        self.add_selection(project.get_selection())
        
    def selection_changed(self, selection):
        """Callback on selection update"""
        self.update_dims(selection.keys())
        self.add_selection(selection)
        self._update_current_dim()
        
    def get_selection_iter(self, dimname, selection):
        i = self._dim_list[dimname]
        if not i:
            return None

        children = self.store.iter_children(i)
        if not children:
            return None

        while children:
            if self.store.get(children, 1)[0] == selection:
                return self.store.get(children, 1)[0]
            children = self.store.iter_next(children)
        return None

    def dataset_changed(self):
        """Callback when new datasets are created"""
        self.selection_changed(self.project.get_selection())        
        for sel in self.project.selections:
            if not sel in self._selections:
                self._selections.append(sel)
                self.add_selection(sel)

    def update_dims(self, dim_list):
        """Update the list of dimensions shown"""
        for dim in dim_list:
            if not self._dim_list.has_key(dim):
                d = self.store.insert_after(None, None, (dim, None))
                self._dim_list[dim] = d

    def add_selection(self, selection):
        for dim in selection.dims():
            if not self.get_selection_iter(dim, selection):
                d = self._dim_list[dim]
                i = self.store.insert_after(d, None, (selection.title, selection))

    def _update_current_dim(self):
        if not self._current_dim or not self._current_selection:
            return
        id_list = self._current_selection[self._current_dim]
        self._identifier_list.set_identifiers(id_list)

    # Callbacks
    def _on_row_activated(self, treeview, path, column):
        self.project.set_selection(self._current_dim, 
                                   self._current_selection[self._current_dim])

    def _on_cursor_changed(self, treeview):        
        cursor = self.get_cursor()[0]
        i = self.store.get_iter(cursor)
        p = self.store.iter_parent(i)
        if p == None:
            self._current_selection = None
        else:
            self._current_dim = self.store.get_value(p, 0)
            self._current_selection = self.store.get_value(i, 1)
        self._update_current_dim()

    def _on_set_selection(self, *rest):
        if not self._current_selection:
            return
        self.project.set_selection(self._current_dim, 
                                   self._current_selection[self._current_dim])

    def _on_button_press_event(self, widget, event):
        if event.button == 3:
            self._menu.popup(None, None, None, event.button, event.time)

    def _on_popup_menu(self):
        pass

class IdentifierList(gtk.TreeView):

    def __init__(self):
        self.store = gtk.ListStore(gobject.TYPE_STRING)
        gtk.TreeView.__init__(self, self.store)
        self.set_headers_visible(True)

        # Set up identifier column to show active identifiers
        renderer = gtk.CellRendererText()
        ids_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
        self.insert_column(ids_column, 0)

    def set_identifiers(self, identifiers):
        "Show the list of identifier strings."
        self.store.clear()
        for e in identifiers:
            self.store.append((e,))