from gi.repository import Gtk, Gio, GLib, GObject, Adw
from threading import Thread
from giara.confManager import ConfManager
from giara.constants import RESOURCE_PREFIX
from giara.giara_clamp import new_clamp_scrollable
from giara.common_post_box import CommonPostBox
from giara.network_cache import CachedSubreddit
from giara.praw_stream_loader import PrawStreamWrapper


class PostPreview(CommonPostBox):
    def __init__(self, **kwargs):
        self.confman = ConfManager()
        super().__init__(
            Gtk.Builder.new_from_resource(
                f'{RESOURCE_PREFIX}/ui/post_preview.ui'
            ),
            **kwargs
        )
        self.get_style_context().add_class('card')
        self.get_style_context().add_class('activatable')

        def hide_show_image(*args):
            img_cont = self.builder.get_object('image_container')
            if self.confman.conf['show_thumbnails_in_preview']:
                img_cont.set_visible(True)
                if img_cont.get_first_child() is None:
                    self.set_post_image()
            else:
                img_cont.set_visible(False)

        self.confman.connect(
            'on_show_thumbnails_in_preview_changed',
            hide_show_image
        )

    def set_entity(self, entity):
        super().set_entity(entity)

    def set_post_image(self):
        if self.confman.conf['show_thumbnails_in_preview']:
            super().set_post_image()


class PrawEntityWrapper(GObject.Object):
    def __init__(self, entity):
        super().__init__()
        self.entity = entity


class PostPreviewListView(Adw.Bin):
    def __init__(self, gen_func, show_post_func, source, load_now=True):
        super().__init__()
        self.clamp = new_clamp_scrollable()
        self.set_child(self.clamp)
        self.source = source
        self.gen_func = gen_func
        self.show_post_func = show_post_func

        # liststore stuff
        self.stream_wrapper = None
        self.loading = False
        self.stop_loading = False
        self.initialized = False
        self.list_store = Gio.ListStore.new(PrawEntityWrapper)

        # listview and factory
        self.factory = Gtk.SignalListItemFactory()
        self.factory.connect('setup', self.on_setup_listitem)
        self.factory.connect('bind', self.on_bind_listitem)
        self.selection = Gtk.NoSelection.new(self.list_store)
        self.list_view = Gtk.ListView.new(self.selection, self.factory)
        self.list_view.get_style_context().add_class('card-list')
        self.list_view.set_vscroll_policy(Gtk.ScrollablePolicy.MINIMUM)
        self.list_view.set_vexpand(False)
        self.list_view.set_valign(Gtk.Align.START)
        self.clamp.set_child(self.list_view)
        self.list_view.set_single_click_activate(True)
        self.list_view.connect('activate', self.on_activate)
        if load_now:
            self.load_more()

    def on_activate(self, lv, row_index):
        data = self.list_store.get_item(row_index)
        self.show_post_func(data.entity)

    def set_gen_func(self, gen_func):
        self.stream_wrapper = PrawStreamWrapper(
            self.source, gen_func.__name__, gen_func
        )
        self.gen_func = gen_func

    def refresh(self, *args):
        self.stop_loading = True
        self.list_store.remove_all()
        self.set_gen_func(self.gen_func)
        self.load_more()

    def load_more(self):

        def process_target(target):
            # hopefully unlazy praw entities
            if hasattr(target.entity, 'title'):
                target.entity.title
            elif hasattr(target.entity, 'body'):
                target.entity.body
            if hasattr(target.entity, 'subreddit'):
                target.entity.cached_subreddit = CachedSubreddit(
                    target.entity.subreddit, target.entity.subreddit_id
                )
                # target.entity.subreddit.title

            GLib.idle_add(
                cb, target,
                priority=GLib.PRIORITY_LOW
            )

        def af():
            if self.loading:
                return
            self.loading = True
            if self.stream_wrapper is None:
                self.set_gen_func(self.gen_func)
            for n in range(10):
                if self.stop_loading:
                    break
                try:
                    self.stream_wrapper.load_more()
                    target = PrawEntityWrapper(self.stream_wrapper.queue_get())
                    Thread(
                        target=process_target, args=(target,), daemon=True
                    ).start()
                except StopIteration:
                    break
            self.loading = False

        def cb(n_item):
            self.list_store.append(n_item)
            self.initialized = True

        self.stop_loading = False
        Thread(target=af, daemon=True).start()

    def on_setup_listitem(self, factory: Gtk.ListItemFactory,
                          list_item: Gtk.ListItem):
        post_preview = PostPreview()
        list_item.set_child(post_preview)
        list_item.post_preview = post_preview

    def on_bind_listitem(self, factory: Gtk.ListItemFactory,
                         list_item: Gtk.ListItem):
        list_item.get_child().set_entity(
            list_item.get_item().entity
        )
