import logging
from gi.repository import Gtk, Gdk, GObject


class ListModel(GObject.GObject, Gtk.TreeModel, Gtk.TreeDragSource):

    COLUMN_UID = 0
    COLUMN_FAVORITE = 1
    COLUMN_ICON = 2
    COLUMN_ICON_COLOR = 3
    COLUMN_TITLE = 4
    COLUMN_TIMESTAMP = 5
    COLUMN_CREATION_TIME = 6
    COLUMN_FILESIZE = 7
    COLUMN_PROGRESS = 8
    COLUMN_BUDDY_1 = 9
    COLUMN_BUDDY_2 = 10
    COLUMN_BUDDY_3 = 11

    _COLUMN_TYPES = {
        COLUMN_UID: str,
        COLUMN_FAVORITE: bool,
        COLUMN_ICON: str,
        COLUMN_ICON_COLOR: object,
        COLUMN_TITLE: str,
        COLUMN_TIMESTAMP: str,
        COLUMN_CREATION_TIME: str,
        COLUMN_FILESIZE: str,
        COLUMN_PROGRESS: int,
        COLUMN_BUDDY_1: object,
        COLUMN_BUDDY_3: object,
        COLUMN_BUDDY_2: object,
    }

    _PAGE_SIZE = 10

    def __init__(self):
        GObject.GObject.__init__(self)

        self._last_requested_index = None
        self._rows = [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11]
        self._temp_drag_file_path = None

    def get_metadata(self, path):
        return 'No metadata'

    def do_get_n_columns(self):
        return len(ListModel._COLUMN_TYPES)

    def do_get_column_type(self, index):
        return ListModel._COLUMN_TYPES[index]

    def do_iter_n_children(self, iterator):
        if iterator == None:
            return len(self._rows)
        else:
            return 0

    def do_get_value(self, iterator, column):
        return self._rows[column]

    def do_iter_nth_child(self, parent_iter, n):
        return (False, None)

    def do_get_path(self, iterator):
        treepath = Gtk.TreePath((iterator.user_data,))
        return treepath

    def do_get_iter(self, path):
        idx = path.get_indices()[0]
        iterator = Gtk.TreeIter()
        iterator.user_data = idx
        return (True, iterator)

    def do_iter_next(self, iterator):
        idx = iterator.user_data + 1
        if idx >= len(self._rows):
            iterator.stamp = -1
            return (False, iterator)
        else:
            iterator.user_data = idx
            return (True, iterator)

    def do_get_flags(self):
        return Gtk.TreeModelFlags.ITERS_PERSIST | Gtk.TreeModelFlags.LIST_ONLY

    def do_iter_children(self, iterator):
        return (False, iterator)

    def do_iter_has_child(self, iterator):
        return False

    def do_iter_parent(self, iterator):
        return (False, Gtk.TreeIter())


    ### BUG: do_drag_data_get does receive only "path" instead "path"
    ### AND "selection". Gtk3 Docs here:
    ### http://developer.gnome.org/gtk3/3.6/gtk3-GtkTreeView-drag-and-drop.html#gtk-tree-drag-source-drag-data-get

    ### gtk2 Docs here:
    ### http://www.pygtk.org/docs/pygtk/class-gtktreedragsource.html#method-gtktreedragsource--drag-data-get
    def do_drag_data_get(self, path, selection):
        uid = self[path][ListModel.COLUMN_UID]
        if selection.target == 'text/uri-list':
            # Get hold of a reference so the temp file doesn't get deleted
            self._temp_drag_file_path = '/tmp/model.test.txt'
            logging.debug('putting %r in selection', self._temp_drag_file_path)
            selection.set(selection.target, 8, self._temp_drag_file_path)
            return True
        elif selection.target == 'journal-object-id':
            selection.set(selection.target, 8, uid)
            return True

        return False


class DropArea(Gtk.Label):

    def __init__(self):
        Gtk.Label.__init__(self, "Drop something on me!")
        self.drag_dest_set(Gtk.DestDefaults.ALL,
                           [],
                           Gdk.DragAction.COPY)

        self.drag_dest_add_text_targets()


def main():
    window = Gtk.Window()
    hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
    model = ListModel()

    tree = Gtk.TreeView()
    tree.set_model(model)
    hbox.add(tree)

    tree.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
                                  [],
                                  Gdk.DragAction.COPY)

    tree.drag_source_add_text_targets()

    renderer = Gtk.CellRendererText()
    column = Gtk.TreeViewColumn('Drag N Drop Example', renderer, text=0)
    tree.append_column(column)

    label = DropArea()
    hbox.add(label)

    window.add(hbox)
    window.connect("destroy", Gtk.main_quit)
    window.show_all()
    Gtk.main()

if __name__ == "__main__":
    main()
