# -*- coding: UTF-8 -*-
# Copyright 2013-2019 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

from builtins import object

from django.db import models
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.conf import settings

from lino.api import dd, rt, _

from lino.mixins import CreatedModified, BabelNamed
from lino.modlib.users.mixins import UserAuthored
from lino.modlib.notify.mixins import ChangeNotifier
from lino.modlib.gfks.mixins import Controllable
from lino.modlib.memo.mixins import Previewable
from .choicelists import CommentEvents
from .mixins import Commentable
# from .choicelists import PublishAllComments, PublishComment



if dd.is_installed("inbox"):
    from lino_xl.lib.inbox.models import comment_email

class CommentType(BabelNamed):
    class Meta(object):
        abstract = dd.is_abstract_model(__name__, 'CommentType')
        verbose_name = _("Comment Type")
        verbose_name_plural = _("Comment Types")



class Comment(CreatedModified, UserAuthored, Controllable,
              ChangeNotifier, Previewable):
    class Meta(object):
        app_label = 'comments'
        abstract = dd.is_abstract_model(__name__, 'Comment')
        verbose_name = _("Comment")
        verbose_name_plural = _("Comments")

    reply_to = dd.ForeignKey(
        'self', blank=True, null=True, verbose_name=_("Reply to"))
    # more_text = dd.RichTextField(_("More text"), blank=True)

    private = models.BooleanField(
        _("Private"), default=dd.plugins.comments.private_default)

    comment_type = dd.ForeignKey('comments.CommentType', blank=True, null=True)

    def __str__(self):
        return u'%s #%s' % (self._meta.verbose_name, self.pk)
        # return _('{user} {time}').format(
        #     user=self.user, obj=self.owner,
        #     time=naturaltime(self.modified))

    @classmethod
    def get_user_queryset(cls, user):
        qs = super(Comment, cls).get_user_queryset(user)

        if not user.user_type.has_required_roles([CommentsReader]):
            return qs.none()

        filters = []
        for m in rt.models_by_base(Commentable):
            flt = m.get_comments_filter(user)
            if flt is not None:
                ct = rt.models.contenttypes.ContentType.objects.get_for_model(m)
                filters.append(flt | ~Q(owner_type=ct))
        if len(filters):
            qs = qs.filter(*filters)
        return qs.distinct()  # add distinct because filter might be on a join

    # def after_ui_create(self, ar):
    #     super(Comment, self).after_ui_create(ar)
    #     if self.owner_id:
    #         self.private = self.owner.is_comment_private(self, ar)

    def on_create(self, ar):
        super(Comment, self).on_create(ar)
        if self.owner_id:
            self.private = self.owner.is_comment_private(self, ar)

    def after_ui_save(self, ar, cw):
        super(Comment, self).after_ui_save(ar, cw)
        if self.owner_id:
            self.owner.on_commented(self, ar, cw)
        if dd.is_installed("memo"):
            ref_objects = settings.SITE.plugins.memo.parser.get_referred_objects(self.body)
            for ref_object in ref_objects:
                created_mention = Mention(comment=self,
                        owner_id=ref_object.pk,
                        owner_type=ContentType.objects.get_for_model(ref_object.__class__))
                created_mention.touch()
                created_mention.save()

    # def full_clean(self):
    #     super(Comment, self).full_clean()
    #     self.owner.setup_comment(self)

    def get_change_owner(self):
        return self.owner or self

    # def get_change_message_type(self, ar):
    #     if self.published is None:
    #         return None
    #     return super(Comment, self).get_change_message_type(ar)

    def get_change_observers(self, ar=None):
        if isinstance(self.owner, ChangeNotifier):
            obs = self.owner
        else:
            obs = super(Comment, self)
        for u in obs.get_change_observers(ar):
            yield u

    def get_change_subject(self, ar, cw):
        if cw is None:
            s = _("{user} commented on {obj}")
        else:
            s = _("{user} modified comment on {obj}")
        return s.format(user=ar.get_user(), obj=self.owner)

    def get_change_body(self, ar, cw):
        if cw is None:
            s = _("{user} commented on {obj}")
        else:
            s = _("{user} modified comment on {obj}")
        user = ar.get_user()
        s = s.format(
            user=user, obj=ar.obj2memo(self.owner))
        if dd.is_installed("inbox"):
            #mailto:ADDR@HOST.com?subject=SUBJECT&body=Filling%20in%20the%20Body!%0D%0Afoo%0D%0Abar
            s += ' <a href="{href}">{reply}</a>'.format(
                href=comment_email.gen_href(self, user),
                reply=_("Reply"))

        s += ':<br>' + self.body
        # if False:
        #     s += '\n<p>\n' + self.more_text
        return s

    @classmethod
    def setup_parameters(cls, fields):
        fields.update(
            observed_event=CommentEvents.field(blank=True))
        fields.update(
            start_date=models.DateField(
                _("Period from"), blank=True, null=True,
                help_text=_("Start date of observed period")))
        fields.update(
            end_date=models.DateField(
                _("until"),
                blank=True, null=True,
                help_text=_("End date of observed period")))
        # fields.update(
        #     show_published=dd.YesNo.field(_("Published"), blank=True))
        super(Comment, cls).setup_parameters(fields)

    @classmethod
    def get_request_queryset(cls, ar, **filter):
        qs = super(Comment, cls).get_request_queryset(ar, **filter)
        pv = ar.param_values
        if pv.observed_event:
            qs = pv.observed_event.add_filter(qs, pv)
        # if pv.show_published == dd.YesNo.yes:
        #     qs = qs.filter(published__isnull=False)
        # elif pv.show_published == dd.YesNo.no:
        #     qs = qs.filter(published__isnull=True)
        return qs

dd.update_field(Comment, 'user', editable=False)
Comment.update_controller_field(verbose_name=_('Topic'))

class Mention(CreatedModified, Controllable, UserAuthored):

    class Meta(object):
        app_label = 'comments'
        abstract = dd.is_abstract_model(__name__, 'Mention')
        verbose_name = _("Mention")
        verbose_name_plural = _("Mentions")

    comment = dd.ForeignKey('comments.Comment', blank=True, null=True)

from .ui import *
