# coding=utf-8

from __future__ import absolute_import

from celery import shared_task
from django.db import transaction

from social.models import SocialInfo, Feed, BigVMailBox
from social.types import in_feed_reason_convert_for_fan
from gm_types.gaia import (
    FEED_ITEM_TYPE,
    IN_FEED_REASON
)
from social.utils import ts_now_as_score


@shared_task
@transaction.atomic
def create_feed(
        uid, follow_uid, topic_id, feed_reason,
        action_item_id=None, score=None, push_to_fans=True,
        tag_id=None, item_type=FEED_ITEM_TYPE.TOPIC):
    """create a new feed.

    NOTE:
        if user is a big_v, we should set push_to_fans as False

    args:
        push_to_fans: if this feed should be pushed to fans
    """
    push_to_fans_only = False
    if feed_reason in (
            IN_FEED_REASON.MY_TOPIC_VOTE,
            IN_FEED_REASON.MY_TOPIC_REPLY,
            IN_FEED_REASON.MY_DIARY_VOTE,
            IN_FEED_REASON.MY_DIARY_REPLY
    ):
        # dont trigger post save if user vote or reply a topic
        # dont push these two types into user's own feed
        push_to_fans_only = True

    # return fast if this is true
    if push_to_fans_only and not push_to_fans:
        return

    if not score:
        score = ts_now_as_score()

    if not push_to_fans_only:
        f, created = Feed.get_or_create(
            uid=uid, item_id=topic_id,
            item_type=item_type, feed_reason=feed_reason,
            score=score,
        )

        if created or (
                feed_reason not in (IN_FEED_REASON.FOLLOW_TAG,
                                    IN_FEED_REASON.FOLLOW_TAG_DIARY,
                                    IN_FEED_REASON.RECOMMEND_TOPIC,
                                    IN_FEED_REASON.FOLLOW_TAG_COMMENT,
                                    )
                and feed_reason == f.feed_reason):
            f.reason_count += 1
            f.save()
            SocialInfo.push_to_feed(f, score, tag_id or action_item_id)

        # if user is a bigv dont add feeditems for fans
        # cache it in a mailbox, it's fans will pull from this mailbox
        # 5.9 add two more reason to feed
        if created and SocialInfo.is_big_v(uid) and feed_reason in (
            IN_FEED_REASON.MY_TOPIC_VOTE,
            IN_FEED_REASON.MY_TOPIC_REPLY,
            IN_FEED_REASON.MY_TOPIC,
            IN_FEED_REASON.MY_DIARY_VOTE,
            IN_FEED_REASON.MY_DIARY_REPLY
        ):
            mailbox = BigVMailBox(uid)
            mailbox.push(f.id)
            push_to_fans = False

    if SocialInfo.is_big_v(uid):
        return

    # chcek if we should push feeds to fans' feed
    if not push_to_fans:
        return

    # only some of the in_feed_reason can be converted
    feed_reason_for_fan = in_feed_reason_convert_for_fan(feed_reason)
    if not feed_reason_for_fan:
        return

    add_feed_for_fans(uid, topic_id, feed_reason_for_fan, action_item_id, score, item_type)


@shared_task
def add_feed_for_fans(uid, topic_id, feed_reason, action_item_id=None, score=None, item_type=FEED_ITEM_TYPE.TOPIC):
    """add feeditem record, which wil call a async task to update fans' feeds."""
    si = SocialInfo.social_info(uid)
    for fan_uid in si.get_fans_iterator():
        create_feed(
            fan_uid, si.uid,
            topic_id, feed_reason,
            action_item_id,
            push_to_fans=False,  # dont broadcast to fan's fans
            score=score,
            item_type=item_type
        )