#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008  Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

"""
Provide a simplified table creation interface
"""

import copy
from gettext import gettext as _

import gen.lib
import Errors
import DateHandler

class SimpleTable:
    """
    Provide a simplified table creation interface.
    """

    def __init__(self, access, doc, title=None):
        """
        Initialize the class with a simpledb, and simpledoc
        """
        self.access = access
        self.simpledoc = doc # simpledoc; simpledoc.doc = docgen object
        self.title = title
        self.__columns = []
        self.__rows = []
        self.__link = []
        self.__sort_col = None
        self.__sort_reverse = False
        self.__link_col = None
        self.__callback_leftclick = None
        self.__callback_leftdouble = None

    def get_row_count(self):
        return len(self.__rows)

    def columns(self, *columns):
        """
        Set the columns
        """
        self.__columns = list(copy.copy(columns))
        self.__sort_vals = [[] for i in range(len(self.__columns))]

    def set_callback(self, which, callback):
        """
        Override (or add) a function for click/double-click
        """
        if which == "leftclick":
            self.__callback_leftclick = callback
        elif which == "leftdouble":
            self.__callback_leftdouble = callback

    def on_table_doubleclick(self, obj, path, view_column):
        """
        Handle events on tables. obj is a treeview
        """
        from Editors import (EditPerson, EditEvent, EditFamily, EditSource,
                             EditPlace, EditRepository)
        selection = obj.get_selection()
        store, node = selection.get_selected()
        if not node:
            return
        index = store.get_value(node, 0) # index
        if self.__callback_leftdouble:
            self.__callback_leftdouble(store.get_value(node, 1))
            return True
        elif self.__link[index]:
            objclass, handle = self.__link[index]
            if objclass == 'Person':
                person = self.access.dbase.get_person_from_handle(handle)
                try:
                    EditPerson(self.simpledoc.doc.dbstate, 
                               self.simpledoc.doc.uistate, [], person)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
            elif objclass == 'Event':
                event = self.access.dbase.get_event_from_handle(handle)
                try:
                    EditEvent(self.simpledoc.doc.dbstate, 
                              self.simpledoc.doc.uistate, [], event)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
            elif objclass == 'Family':
                ref = self.access.dbase.get_family_from_handle(handle)
                try:
                    EditFamily(self.simpledoc.doc.dbstate, 
                               self.simpledoc.doc.uistate, [], ref)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
            elif objclass == 'Source':
                ref = self.access.dbase.get_source_from_handle(handle)
                try:
                    EditSource(self.simpledoc.doc.dbstate, 
                               self.simpledoc.doc.uistate, [], ref)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
            elif objclass == 'Place':
                ref = self.access.dbase.get_place_from_handle(handle)
                try:
                    EditPlace(self.simpledoc.doc.dbstate, 
                               self.simpledoc.doc.uistate, [], ref)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
            elif objclass == 'Repository':
                ref = self.access.dbase.get_repository_from_handle(handle)
                try:
                    EditRepository(self.simpledoc.doc.dbstate, 
                               self.simpledoc.doc.uistate, [], ref)
                    return True # handled event
                except Errors.WindowActiveError:
                    pass
        return False # didn't handle event

    def on_table_click(self, obj):
        """
        Handle events on tables. obj is a treeview
        """
        selection = obj.get_selection()
        store, node = selection.get_selected()
        if not node:
            return
        index = store.get_value(node, 0) # index
        if self.__callback_leftclick:
            self.__callback_leftclick(store.get_value(node, 1))
            return True
        elif self.__link[index]:
            objclass, handle = self.__link[index]
            if objclass == 'Person':
                person = self.access.dbase.get_person_from_handle(handle)
                self.simpledoc.doc.dbstate.change_active_person(person)
                return True
        return False # didn't handle event

    def row_sort_val(self, col, val):
        """
        Add a row of data to sort by.
        """
        self.__sort_vals[col].append(val) 

    def set_link_col(self, col):
        """
        Manually sets the column that defines link.
        """
        self.__link_col = col

    def row(self, *data):
        """
        Add a row of data.
        """
        retval = [] 
        link   = None
        for col in range(len(data)):
            item = data[col]
            # FIXME: add better text representations of these objects
            if type(item) in [str, unicode]:
                retval.append(item)
            elif type(item) in [int, float, long]:
                retval.append(item)
                self.row_sort_val(col, item)
            elif isinstance(item, gen.lib.Person):
                name = self.access.name(item)
                retval.append(name)
                if (self.__link_col == col or link == None):
                    link = ('Person', item.handle)
            elif isinstance(item, gen.lib.Family): 
                father = self.access.father(item)
                mother = self.access.mother(item)
                text = ""
                if father:
                    text += " " + self.access.name(father)
                else:
                    text += " " + _("Unknown father")
                text += " " + _("and")
                if mother:
                    text += " " + self.access.name(mother)
                else:
                    text += " " + _("Unknown mother")
                retval.append(text)
                if (self.__link_col == col or link == None):
                    link = ('Family', item.handle)
            elif isinstance(item, gen.lib.Source): 
                retval.append(_('Source'))
                if (self.__link_col == col or link == None):
                    link = ('Souce', item.handle)
            elif isinstance(item, gen.lib.Event):
                name = self.access.event_type(item)
                retval.append(name)
                if (self.__link_col == col or link == None):
                    link = ('Event', item.handle)
            elif isinstance(item, gen.lib.MediaObject):
                retval.append(_('Media'))
                if (self.__link_col == col or link == None):
                    link = ('Media', item.handle)
            elif isinstance(item, gen.lib.Place):
                retval.append(_('Place'))
                if (self.__link_col == col or link == None):
                    link = ('Place', item.handle)
            elif isinstance(item, gen.lib.Repository):
                retval.append(_('Repository'))
                if (self.__link_col == col or link == None):
                    link = ('Repository', item.handle)
            elif isinstance(item, gen.lib.Note):
                retval.append(_('Note'))
                if (self.__link_col == col or link == None):
                    link = ('Note', item.handle)
            elif isinstance(item, gen.lib.Date):
                text = DateHandler.displayer.display(item)
                retval.append(text)
                self.row_sort_val(col, item.sortval)
                if (self.__link_col == col or link == None):
                    link = ('Date', item)
            else:
                raise AttributeError, ("unknown object type: '%s': %s" % 
                                       (item, type(item)))
        self.__link.append(link)
        self.__rows.append(retval)

    def sort(self, column_name, reverse=False):
        self.__sort_col = column_name
        self.__sort_reverse = reverse

    def __sort(self):
        idx = self.__columns.index(self.__sort_col)
        if self.__sort_reverse:
            self.__rows.sort(lambda a, b: -cmp(a[idx],b[idx]))
        else:
            self.__rows.sort(lambda a, b: cmp(a[idx],b[idx]))

    def write(self):
        if self.simpledoc.doc.type == "standard":
            doc = self.simpledoc.doc
            doc.start_table('simple','Table')
            columns = len(self.__columns)
            if self.title:
                doc.start_row()
                doc.start_cell('TableHead',columns)
                doc.start_paragraph('TableTitle')
                doc.write_text(_(self.title))
                doc.end_paragraph()
                doc.end_cell()
                doc.end_row()
            if self.__sort_col:
                self.__sort()
            doc.start_row()
            for col in self.__columns:
                doc.start_cell('TableNormalCell',1)
                doc.write_text(col,'TableTitle')
                doc.end_cell()
            doc.end_row()
            for row in self.__rows:
                doc.start_row()
                for col in row:
                    doc.start_cell('TableNormalCell',1)
                    doc.write_text(col,'Normal')
                    doc.end_cell()
                doc.end_row()
            doc.end_table()
            doc.start_paragraph("Normal")
            doc.end_paragraph()
        elif self.simpledoc.doc.type == "gtk":
            import gtk
            buffer = self.simpledoc.doc.buffer
            text_view = self.simpledoc.doc.text_view
            model_index = 1 # start after index
            if self.__sort_col:
                sort_index = self.__columns.index(self.__sort_col)
            else:
                sort_index = 0
            treeview = gtk.TreeView()
            treeview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
            treeview.connect('row-activated', self.on_table_doubleclick)
            treeview.connect('cursor-changed', self.on_table_click)
            renderer = gtk.CellRendererText()
            types = [int] # index
            cnt = 0
            sort_data = []
            sort_data_types = []
            for col in self.__columns:
                types.append(type(col))
                column = gtk.TreeViewColumn(col,renderer,text=model_index)
                if self.__sort_vals[cnt] != []:
                    sort_data.append(self.__sort_vals[cnt])
                    column.set_sort_column_id(len(self.__columns) + 
                                              len(sort_data))
                    sort_data_types.append(int)
                else:
                    column.set_sort_column_id(model_index)
                treeview.append_column(column)
                #if model_index == sort_index:
                # FIXME: what to set here?    
                model_index += 1
                cnt += 1
            if self.title:
                self.simpledoc.paragraph(self.title)
            # Make a GUI to put the tree view in
            types += sort_data_types
            model = gtk.ListStore(*types)
            treeview.set_model(model)
            iter = buffer.get_end_iter()
            anchor = buffer.create_child_anchor(iter)
            text_view.add_child_at_anchor(treeview, anchor)
            count = 0
            for data in self.__rows:
                model.append(row=([count] + list(data) + [col[count] for col in sort_data]))
                count += 1
            text_view.show_all()
            self.simpledoc.paragraph("")
            self.simpledoc.paragraph("")
