# Python imports
import asyncio

# Lib imports
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from gi.repository import GLib

# Application imports
from ...widgets.tab_header_widget import TabHeaderWidget
from ...widgets.icon_grid_widget import IconGridWidget
from ...widgets.icon_tree_widget import IconTreeWidget



class GridMixin:
    """docstring for GridMixin"""

    def load_store(self, tab, store, save_state = False, use_generator = False):
        dir   = tab.get_current_directory()
        files = tab.get_files()

        for file in files:
            store.append([None, file[0]])

        Gtk.main_iteration()
        if use_generator:
            # NOTE: tab > icon > _get_system_thumbnail_gtk_thread must not be used
            # as the attempted promotion back to gtk threading stalls the generator. (We're already in main gtk thread)
            for i, icon in enumerate( self.create_icons_generator(tab, dir, files) ):
                self.load_icon(i, store, icon)
        else:
            # for i, file in enumerate(files):
            #     self.create_icon(i, tab, store, dir, file[0])
            try:
                loop = asyncio.get_running_loop()
            except RuntimeError:
                loop = None

            if loop and loop.is_running():
                loop.create_task( self.create_icons(tab, store, dir, files) )
            else:
                asyncio.run( self.create_icons(tab, store, dir, files) )

        # NOTE: Not likely called often from here but it could be useful
        if save_state and not trace_debug:
            self.fm_controller.save_state()

    async def create_icons(self, tab, store, dir, files):
        tasks = [self.update_store(i, store, dir, tab, file[0]) for i, file in enumerate(files)]
        await asyncio.gather(*tasks)

    async def load_icon(self, i, store, icon):
        self.update_store(i, store, icon)

    async def update_store(self, i, store, dir, tab, file):
        icon = tab.create_icon(dir, file)
        itr  = store.get_iter(i)
        store.set_value(itr, 0, icon)

    def create_icons_generator(self, tab, dir, files):
        for file in files:
            icon = tab.create_icon(dir, file[0])
            yield icon

    # @daemon_threaded
    # def create_icon(self, i, tab, store, dir, file):
    #     icon = tab.create_icon(dir, file)
    #     GLib.idle_add(self.update_store, *(i, store, icon,))
    #
    # @daemon_threaded
    # def load_icon(self, i, store, icon):
    #     GLib.idle_add(self.update_store, *(i, store, icon,))

    # def update_store(self, i, store, icon):
    #     itr = store.get_iter(i)
    #     store.set_value(itr, 0, icon)

    def create_tab_widget(self, tab):
        return TabHeaderWidget(tab, self.close_tab)

    def create_scroll_and_store(self, tab, wid, use_tree_view = False):
        scroll = Gtk.ScrolledWindow()

        if not use_tree_view:
            grid = self.create_icon_grid_widget()
        else:
            # TODO: Fix global logic to make the below work too
            grid = self.create_icon_tree_widget()

        scroll.add(grid)
        scroll.set_name(f"{wid}|{tab.get_id()}")
        grid.set_name(f"{wid}|{tab.get_id()}")
        self.builder.expose_object(f"{wid}|{tab.get_id()}|icon_grid", grid, use_gtk = False)
        self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll, use_gtk = False)

        return scroll, grid.get_store()

    def create_icon_grid_widget(self):
        grid = IconGridWidget()
        grid._setup_additional_signals(
            self.grid_icon_single_click,
            self.grid_icon_double_click,
            self.grid_set_selected_items,
            self.grid_on_drag_set,
            self.grid_on_drag_data_received,
            self.grid_on_drag_motion
        )

        return grid

    def create_icon_tree_widget(self):
        grid = IconTreeWidget()
        grid._setup_additional_signals(
            self.grid_icon_single_click,
            self.grid_icon_double_click,
            self.grid_on_drag_set,
            self.grid_on_drag_data_received,
            self.grid_on_drag_motion
        )

        grid.columns_autosize()
        return grid

    def get_store_and_label_from_notebook(self, notebook, _name):
        icon_grid = None
        tab_label = None
        store     = None

        for obj in notebook.get_children():
            icon_grid = obj.get_children()[0]
            name      = icon_grid.get_name()
            if name == _name:
                store     = icon_grid.get_model()
                tab_label = notebook.get_tab_label(obj).get_children()[0]

        return store, tab_label

    def get_icon_grid_from_notebook(self, notebook, _name):
        for obj in notebook.get_children():
            icon_grid = obj.get_children()[0]
            name      = icon_grid.get_name()
            if name == _name:
                return icon_grid
