from gettext import gettext as _
from giara.path_utils import is_image, is_media
from giara.download_manager import download_img, download_video
from gi.repository import Gtk, GLib, Gdk, Gio
from praw.models import Comment, Submission, Message
from threading import Thread
from giara.new_post_window import EditWindow
from giara.picture_view import PictureView
from giara.flair_label import FlairLabel
from giara.time_utils import humanize_utc_timestamp
from giara.confManager import ConfManager
from giara.simple_avatar import SimpleAvatar


class InteractiveEntityBox(Gtk.Bin):
    def __init__(self, entity, builder, **kwargs):
        super().__init__(**kwargs)
        self.entity = entity
        self.builder = builder

        self.save_btn = self.builder.get_object('save_btn')
        self.save_btn.connect('clicked', self.on_save_clicked)
        self.upvotes_label = self.builder.get_object('upvotes_label')
        self.upvote_btn = self.builder.get_object('upvote_btn')
        self.downvote_btn = self.builder.get_object('downvote_btn')
        self.color_up_down_btns()
        self.upvote_btn.connect('clicked', self.on_upvote_btn_clicked)
        self.downvote_btn.connect('clicked', self.on_downvote_btn_clicked)
        self.color_saved_btn()

        confman = ConfManager()
        self.me = confman.reddit_user_me
        self.delete_btn = self.builder.get_object('delete_btn')

        self.share_btn = self.builder.get_object('share_btn')
        if hasattr(self.entity, 'permalink'):
            self.share_btn.set_visible(True)
            self.share_btn.set_no_show_all(False)
            self.share_btn.connect('clicked', self.copy_link)
        else:
            self.share_btn.set_visible(False)
            self.share_btn.set_no_show_all(True)

        self.main_box = self.builder.get_object('main_box')
        self.add(self.main_box)

        self.edit_btn = self.builder.get_object('edit_btn')
        self.show_hide_edit_delete()

        self.author_flairs_container = self.builder.get_object(
            'author_flairs_container'
        )
        if (
                self.author_flairs_container is not None and
                self.entity.author_flair_text is not None
        ):
            self.author_flairs_container.add(
                FlairLabel(
                    self.entity.author_flair_text,
                    self.entity.author_flair_background_color,
                    self.entity.author_flair_text_color
                )
            )

    def show_hide_edit_delete(self):

        def af():
            if self.edit_btn:
                show_edit = (
                    self.entity.author is not None and
                    self.entity.author.fullname == self.me.fullname and
                    (
                        isinstance(self.entity, Comment) or
                        (
                            isinstance(self.entity, Submission) and
                            self.entity.is_self
                        )
                    )
                )
                GLib.idle_add(edit_cb, show_edit)
            if (
                    hasattr(self.entity, 'delete') and
                    hasattr(self.entity, 'author') and
                    self.entity.author == self.me
            ):
                GLib.idle_add(delete_cb)

        def edit_cb(show_edit):
            self.edit_btn.set_visible(show_edit)
            self.edit_btn.set_no_show_all(not show_edit)
            if show_edit:
                self.edit_btn.connect('clicked', self.on_edit_clicked)

        def delete_cb():
            self.delete_btn.set_visible(True)
            self.delete_btn.set_no_show_all(False)
            self.delete_btn.connect('clicked', self.on_delete_clicked)

        Thread(target=af).start()

    def on_delete_clicked(self, *args):
        confirm_dialog = Gtk.MessageDialog(
            flags=(
                Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT
            ),
            message_type=Gtk.MessageType.QUESTION,
            buttons=Gtk.ButtonsType.YES_NO,
            text=_('Are you sure you want to delete this item?')
        )
        confirm_dialog.set_transient_for(self.get_toplevel())
        res = confirm_dialog.run()
        confirm_dialog.close()
        if res == Gtk.ResponseType.YES:
            self.entity.delete()
            if hasattr(self, 'refresh_func'):
                self.refresh_func(wait_for_comments_update=True)

    def on_edit_clicked(self, *args):
        win = EditWindow(
            self.entity,
            lambda *args: (
                self.refresh_func(wait_for_comments_update=True)
                if hasattr(self, 'refresh_func') else None
            )
        )
        win.set_transient_for(self.get_toplevel())
        win.present()
        win.show_all()

    def copy_link(self, *args):
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(
            'https://reddit.com' + (
                '/'
                if self.entity.permalink[0] != '/' else ''
            ) + self.entity.permalink,
            -1
        )
        clipboard.store()
        self.get_toplevel().main_ui.show_notification(
            _('Link copied to clipboard')
        )

    def on_save_clicked(self, *args):

        def af():
            if self.entity.saved:
                self.entity.unsave()
            else:
                self.entity.save()
            self.entity._fetch()

            def cb():
                self.color_saved_btn()
                self.save_btn.set_sensitive(True)

            GLib.idle_add(cb)

        self.save_btn.set_sensitive(False)
        Thread(target=af).start()

    def color_saved_btn(self):
        if hasattr(self.entity, 'saved'):
            self.save_btn.set_visible(True)
            self.save_btn.set_no_show_all(False)
            if self.entity.saved:
                self.save_btn.get_style_context().add_class('blue')
            else:
                self.save_btn.get_style_context().remove_class('blue')
        else:
            self.save_btn.set_visible(False)
            self.save_btn.set_no_show_all(True)

    def on_upvote_btn_clicked(self, *args):

        def af():
            if self.entity.likes:
                self.entity.clear_vote()
            else:
                self.entity.upvote()
            self.entity._fetch()

            def cb():
                self.color_up_down_btns()
                self.downvote_btn.set_sensitive(True)
                self.upvote_btn.set_sensitive(True)

            GLib.idle_add(cb)

        self.upvote_btn.set_sensitive(False)
        self.downvote_btn.set_sensitive(False)
        Thread(target=af).start()

    def on_downvote_btn_clicked(self, *args):

        def af():
            if self.entity.likes or self.entity.likes is None:
                self.entity.downvote()
            else:
                self.entity.clear_vote()
            self.entity._fetch()

            def cb():
                self.color_up_down_btns()
                self.downvote_btn.set_sensitive(True)
                self.upvote_btn.set_sensitive(True)

            GLib.idle_add(cb)

        self.upvote_btn.set_sensitive(False)
        self.downvote_btn.set_sensitive(False)
        Thread(target=af).start()

    def color_up_down_btns(self):
        # also update ups label
        self.upvotes_label.set_text(str(self.entity.score))
        upvote_style_context = self.upvote_btn.get_style_context()
        downvote_style_context = self.downvote_btn.get_style_context()
        if self.entity.likes is None:  # None = no interaction
            upvote_style_context.remove_class('blue')
            downvote_style_context.remove_class('red')
        elif self.entity.likes:  # True = upvote
            upvote_style_context.add_class('blue')
            downvote_style_context.remove_class('red')
        else:  # False = downvote
            upvote_style_context.remove_class('blue')
            downvote_style_context.add_class('red')


class CommonPostBox(InteractiveEntityBox):
    def __init__(self, post, builder, **kwargs):
        super().__init__(post, builder, **kwargs)
        self.post = post
        self.confman = ConfManager()

        self.title_label = self.builder.get_object('title_label')
        self.pinned_icon = self.builder.get_object('pinned_icon')
        if isinstance(self.post, Submission):
            self.title_label.set_text(self.post.title)
            if self.post.stickied:
                self.pinned_icon.set_visible(True)
                self.pinned_icon.set_no_show_all(False)
        elif isinstance(self.post, Comment):
            self.title_label.set_text(_('Comment: ')+self.post.body[:50]+'...')
        else:
            self.title_label.set_text(self.post.body)
        self.datetime_label = self.builder.get_object('datetime_label')
        self.datetime_label.set_text(
            humanize_utc_timestamp(self.post.created_utc)
        )
        self.subreddit_label = self.builder.get_object('subreddit_label')
        if isinstance(self.post, Message):
            self.subreddit_label.set_text(_('Message'))
        else:
            self.subreddit_label.set_text(self.post.subreddit_name_prefixed)
        self.op_label = self.builder.get_object('op_label')
        self.op_label.set_text(
            f'u/{self.post.author.name}'
            if self.post.author is not None else _('Author unknown')
        )
        self.avatar = SimpleAvatar(
            42,
            self.post.subreddit.display_name
            if self.post.subreddit is not None else self.post.author.name,
            self.get_subreddit_icon
        )
        self.builder.get_object('avatar_container').add(self.avatar)

        self.open_media_btn = self.builder.get_object('open_media_btn')
        can_open_media = isinstance(self.post, Submission) and (
            self.post.is_video or
            self.post.is_reddit_media_domain or
            is_media(self.post.url)
        )
        self.is_video = (
            isinstance(self.post, Submission) and
            (self.post.is_video or 'https://v.redd.it' in self.post.url)
        )
        self.open_media_btn.set_visible(can_open_media)
        self.open_media_btn.set_no_show_all(not can_open_media)
        self.open_media_btn.connect(
            'clicked',
            lambda *args: self.open_media()
        )
        self.flairs_container = self.builder.get_object('flairs_container')
        if isinstance(self.post, Submission):
            type_flair = None
            if self.post.is_self:
                type_flair = FlairLabel.new_type_text()
            elif self.is_video:
                type_flair = FlairLabel.new_type_video()
            elif self.post.is_reddit_media_domain:
                type_flair = FlairLabel.new_type_image()
            else:
                type_flair = FlairLabel.new_type_link()
            self.flairs_container.add(type_flair)
            if self.post.link_flair_text:
                self.flairs_container.add(FlairLabel.new_from_post(self.post))
        self.image = None
        self.image_container = self.builder.get_object('image_container')
        self.set_post_image()
        self.open_link_btn = self.builder.get_object('open_link_btn')
        if hasattr(self.post, 'url'):
            self.open_link_btn.set_visible(True)
            self.open_link_btn.set_no_show_all(False)
            if 'http://' in self.post.url or 'https://' in self.post.url:
                self.open_link_btn.connect(
                    'clicked',
                    self.open_link
                )
            else:
                reddit = self.confman.reddit
                self.open_link_btn.connect(
                    'clicked',
                    lambda *args: self.get_toplevel().main_ui.deck.show_post(
                        reddit.submission(url=(
                            'https://reddit.com' +
                            ('/' if self.post.url[0] != '/' else '') +
                            self.post.url
                        ))
                    )
                )
        else:
            self.open_link_btn.set_visible(False)
            self.open_link_btn.set_no_show_all(True)

    def open_link(self, *args):
        url = self.post.url
        print(url)
        if self.confman.conf['twitter2nitter']:
            for pfx in ('twitter.com', 'www.twitter.com', 'mobile.twitter.com'):
                if f'://{pfx}' in url:
                    url = url.replace(f'://{pfx}', '://nitter.net')
                    break
        if self.confman.conf['youtube2invidious']:
            inv = self.confman.conf['invidious_instance']
            for pfx in ('youtube.com', 'www.youtube.com'):
                if f'://{pfx}' in url:
                    url = url.replace(f'://{pfx}', f'://{inv}')
                    break
        print(url)
        Gio.AppInfo.launch_default_for_uri(url)

    def get_subreddit_icon(self):
        if (
                self.post.subreddit is not None and
                is_image(self.post.subreddit.icon_img)
        ):
            return download_img(self.post.subreddit.icon_img)

    def set_post_image(self):

        def af():
            post_img = self.get_post_image_filename()
            if post_img is not None:
                GLib.idle_add(cb, post_img)

        def cb(post_img):
            self.image = PictureView(post_img, self.is_video)
            self.image_container.add(self.image)
            self.image_container.show_all()
            self.image.set_vexpand(False)

        Thread(target=af).start()

    def open_media(self):

        def af():
            path = None
            if self.is_video:
                path = download_video(
                    self.post.media['reddit_video']['fallback_url']
                    if self.post.media
                    else self.post.url+'/DASH_1080.mp4'
                )
            else:
                path = download_img(self.post.url)
            if path is not None:
                Gio.AppInfo.launch_default_for_uri(
                    GLib.filename_to_uri(path)
                )

        Thread(target=af).start()

    def get_post_image_filename(self):
        if isinstance(self.post, Comment):
            return None
        image = 'No image'
        try:
            image = self.post.url
            if not is_image(image):
                if not hasattr(self.post, 'preview'):
                    return None
                image = max([
                    p for p in self.post.preview['images'][0]['resolutions']
                    if p['width'] <= 400
                ], key=lambda prev: prev['width'])['url']
            if is_image(image):
                image_path = download_img(image)
                return image_path
        except Exception:
            print(f'Error creating pixbuf for post image `{image}`')
            return None
