from giara.constants import RESOURCE_PREFIX
from gettext import gettext as _
from gi.repository import Gtk, Adw, GLib
from giara.sections import PostListSection, MarkdownSection
from giara.squeezing_viewswitcher_headerbar import \
    SqueezingViewSwitcherHeaderbar
from threading import Thread
from giara.time_utils import humanize_utc_timestamp
from giara.simple_avatar import SimpleAvatar
from giara.multireddit_list_view import MultiredditsListbox
from giara.confManager import ConfManager
from giara.network_cache import CachedSubreddit
from giara.common_functions import get_subreddit_icon


class MultiPickerListbox(MultiredditsListbox):
    def __init__(self, sub, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.sub = sub
        self.set_filter_func(self.filter_func, None, False)
        self.term = ''
        self.set_selection_mode(Gtk.SelectionMode.SINGLE)
        self.connect('row-activated', self.on_row_activate)
        self.working = False

    def add(self, *args, **kwargs):
        self.append(*args, **kwargs)

    def append(self, row, *args, **kwargs):
        row.in_sub = False
        super().append(row, *args, **kwargs)

        def af():
            row.in_sub = self.sub in row.multi.subreddits
            GLib.idle_add(cb)

        def cb():
            if row.in_sub:
                icon = Gtk.Image.new_from_icon_name(
                    'emblem-ok-symbolic'
                )
                icon.set_tooltip_text(_(
                    'This subreddit is already part of this multireddit'
                ))
                row.main_box.append(icon)
            row.show()

        Thread(target=af, daemon=True).start()

    def on_row_activate(self, lb, row):
        if self.working or row.in_sub:
            return
        self.working = True
        self.set_sensitive(False)

        def af():
            sub = self.sub
            if isinstance(sub, CachedSubreddit):
                sub = sub.subreddit
            row.multi.add(sub)
            GLib.idle_add(cb)

        def cb():
            self.working = False
            self.populate()
            self.set_sensitive(True)

        Thread(target=af, daemon=True).start()

    def set_term(self, term):
        self.term = term.strip()
        self.invalidate_filter()

    def filter_func(self, row, data, notify_destroy):
        return not self.term or self.term.lower() in row.get_key().lower()


class SubredditViewMorePopover(Gtk.Popover):
    def __init__(self, sub, relative_to, **kwargs):
        super().__init__(**kwargs)
        self.confman = ConfManager()
        self.reddit = self.confman.reddit
        self.sub = sub
        self.relative_to = relative_to
        self.set_autohide(True)
        self.set_parent(self.relative_to)
        self.set_size_request(300, 400)
        self.builder = Gtk.Builder.new_from_resource(
            f'{RESOURCE_PREFIX}/ui/subreddit_more_actions.ui'
        )
        self.stack = self.builder.get_object('stack')
        self.stack_container = self.builder.get_object('stack_container')
        self.set_child(self.stack_container)
        self.add_to_multi_box = self.builder.get_object('add_to_multi_box')
        self.add_to_multi_back_btn = self.builder.get_object(
            'add_to_multi_back_btn'
        )
        self.actions_buttons_box = self.builder.get_object(
            'actions_buttons_box'
        )
        self.add_to_multi_btn = self.builder.get_object('add_to_multi_btn')
        self.multi_picker_container = self.builder.get_object(
            'multi_picker_container'
        )
        self.add_to_multi_btn.connect(
            'clicked',
            lambda *args: self.stack.set_visible_child(self.add_to_multi_box)
        )
        self.add_to_multi_back_btn.connect(
            'clicked',
            lambda *args: self.stack.set_visible_child(
                self.actions_buttons_box
            )
        )

        self.picker_builder = Gtk.Builder.new_from_resource(
            f'{RESOURCE_PREFIX}/ui/choice_picker_popover_content.ui'
        )
        self.picker_main_container = self.picker_builder.get_object(
            'main_container'
        )
        self.multi_picker_container.append(self.picker_main_container)
        self.picker_sw = self.picker_builder.get_object('scrolled_win')
        self.picker_lbox = MultiPickerListbox(self.sub)
        self.picker_sw.set_child(self.picker_lbox)
        self.picker_search_entry = self.picker_builder.get_object(
            'search_entry'
        )
        self.picker_search_entry.connect(
            'changed',
            lambda *args: self.picker_lbox.set_term(
                self.picker_search_entry.get_text()
            )
        )

        self.new_multi_box = self.builder.get_object('new_multi_box')
        self.new_multi_name_entry = self.builder.get_object(
            'new_multi_name_entry'
        )
        self.new_multi_create_btn = self.builder.get_object(
            'new_multi_create_btn'
        )
        self.new_multi_btn = self.builder.get_object('new_multi_btn')
        self.new_multi_btn.connect(
            'clicked',
            lambda *args: self.stack.set_visible_child(
                self.new_multi_box
            )
        )
        self.new_multi_create_btn.connect('clicked', self.create_multi)
        self.new_multi_name_entry.connect(
            'changed', self.on_new_multi_name_entry_changed
        )
        self.new_multi_back_btn = self.builder.get_object(
            'new_multi_back_btn'
        )
        self.new_multi_back_btn.connect(
            'clicked', lambda *args: self.stack.set_visible_child(
                self.add_to_multi_box
            )
        )

    def get_new_multi_name(self, *args):
        return self.new_multi_name_entry.get_text().strip()

    def on_new_multi_name_entry_changed(self, *args):
        self.new_multi_create_btn.set_sensitive(
            not not self.get_new_multi_name()
        )

    def create_multi(self, *args):
        name = self.get_new_multi_name()
        if not name:
            return

        def af():
            self.reddit.multireddit.create(
                display_name=name,
                subreddits=[self.sub]
            )
            GLib.idle_add(cb)

        def cb():
            self.stack.set_visible_child(self.add_to_multi_box)
            self.new_multi_name_entry.set_text('')
            self.picker_lbox.populate()

        Thread(target=af, daemon=True).start()


class SubredditViewHeaderbar(SqueezingViewSwitcherHeaderbar):
    def __init__(self, section, sub, stack):
        super().__init__(
            Gtk.Builder.new_from_resource(
                f'{RESOURCE_PREFIX}/ui/subreddit_view_headerbar.ui'
            ),
            section,
            view_switcher=True,
            sort_menu=True,
            sorting_methods={
                'hot': {
                    'name': _('Hot'),
                    'icon': 'hot-symbolic'
                },
                'new': {
                    'name': _('New'),
                    'icon': 'new-symbolic'
                },
                'top': {
                    'name': _('Top'),
                    'icon': 'arrow1-up-symbolic'
                },
                'rising': {
                    'name': _('Rising'),
                    'icon': 'rising-symbolic'
                },
                'controversial': {
                    'name': _('Controversial'),
                    'icon': 'controversial-symbolic'
                }
            },
            stack=stack
        )
        self.sub = sub
        self.refresh_btn = self.builder.get_object('refresh_btn')
        self.back_btn = self.builder.get_object('back_btn')
        self.search_btn = self.builder.get_object('search_btn')

        self.more_btn = Gtk.MenuButton()
        self.more_btn.set_icon_name(
            'view-more-symbolic'
        )
        self.more_popover = SubredditViewMorePopover(self.sub, self.more_btn)
        self.more_btn.set_popover(self.more_popover)
        self.more_btn.set_tooltip_text(_('More actions'))
        self.headerbar.pack_end(self.more_btn)


class SubredditHeading(Gtk.Box):
    def __init__(self, sub, refresh_func, **kwargs):
        super().__init__(**kwargs)
        self.sub = sub
        self.refresh_func = refresh_func
        self.builder = Gtk.Builder.new_from_resource(
            f'{RESOURCE_PREFIX}/ui/subreddit_heading.ui'
        )
        self.main_box = self.builder.get_object('main_box')
        self.avatar_container = self.builder.get_object('avatar_container')
        self.title_label = self.builder.get_object('title_label')
        self.title_label.set_text(self.sub.title)
        self.display_name_label = self.builder.get_object('display_name_label')
        self.display_name_label.set_text(self.sub.display_name_prefixed)
        self.join_btn = self.builder.get_object('join_btn')
        self.join_btn.connect('clicked', self.join_or_leave)
        self.refresh_join_btn()
        self.members_label = self.builder.get_object('members_label')
        self.members_label.set_text(str(self.sub.subscribers))
        self.since_label = self.builder.get_object('since_label')
        self.since_label.set_text(str(
            humanize_utc_timestamp(self.sub.created_utc).split('\n')[0]
        ))

        self.avatar = SimpleAvatar(
            64, self.sub.display_name, self.get_subreddit_icon
        )
        self.avatar_container.append(self.avatar)

        self.append(self.main_box)

    def refresh_join_btn(self, *args):
        join_style_context = self.join_btn.get_style_context()
        for c in ('suggested-action', 'destructive-action'):
            join_style_context.remove_class(c)
        if self.sub.user_is_subscriber:
            join_style_context.add_class('destructive-action')
            self.join_btn.set_label(_('Leave'))
        else:
            join_style_context.add_class('suggested-action')
            self.join_btn.set_label(_('Join'))

    def join_or_leave(self, *args):
        self.join_btn.set_sensitive(False)

        def af():
            if self.sub.user_is_subscriber:
                self.sub.unsubscribe()
            else:
                self.sub.subscribe()
            GLib.idle_add(cb)

        def cb():
            self.refresh_func()

        Thread(target=af, daemon=True).start()

    def get_subreddit_icon(self):
        return get_subreddit_icon(self.sub)


class SubredditView(Gtk.Box):
    def __init__(self, sub, show_post_func, **kwargs):
        super().__init__(orientation=Gtk.Orientation.VERTICAL, **kwargs)
        self.sub = sub
        self.show_post_func = show_post_func
        self.heading = None
        self.stack = Adw.ViewStack(
            vexpand=True
        )
        self.posts_section_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.posts_section = PostListSection(
            self.sub.hot,
            self.show_post_func,
            source=self.sub,
            load_now=True
        )
        self.posts_section_box.append(self.posts_section)
        self.stack.add_titled(
            self.posts_section_box, 'posts', _('Posts')
        ).set_icon_name('view-list-symbolic')
        self.description_section = MarkdownSection(
            self.sub.description
        )
        self.stack.add_titled(
            self.description_section, 'description', _('Description')
        ).set_icon_name('preferences-system-details-symbolic')
        self.headerbar = SubredditViewHeaderbar(
            self.posts_section.listview, self.sub, self.stack
        )
        self.headerbar.refresh_btn.connect('clicked', self.refresh)
        self.bottom_bar = Adw.ViewSwitcherBar(vexpand=False, hexpand=True)
        self.bottom_bar.set_stack(self.stack)
        self.headerbar.connect(
            'squeeze',
            lambda caller, squeezed: self.bottom_bar.set_reveal(squeezed)
        )

        self.append(self.headerbar)
        self.append(self.stack)
        self.append(self.bottom_bar)

    def add_heading(self):
        target_box = self.posts_section_box
        if self.heading is not None:
            target_box.remove(self.heading)
        self.heading = SubredditHeading(self.sub, self.refresh)
        target_box.prepend(self.heading)

    def refresh(self, *args):

        def af():
            self.sub._fetch()
            GLib.idle_add(cb)

        def cb():
            self.posts_section.listview.refresh()
            self.add_heading()

        Thread(target=af, daemon=True).start()
