# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function

import datetime
import json

from django.conf import settings
from django.contrib.auth.models import User
from django.utils import timezone
from django.db.models import Q
from gm_types.gaia import (
    HOMEPAGE_OPERATE_TYPE,
    SLIDE_POSITION,
    GADGET_PAGE_TYPE,
    SMALLIMAGE_TYPE,
    SLIDE_TYPE,
    WORLD_AREA_TYPE,
    SLIDE_LOCATION,
    SLIDE_USER_TYPE,
    SLIDE_PAYMENT_TYPE,
    TAB_TYPES_NEW,
    HOME_PAGE_ICON_VERSION,
    FESTIVAL_HOMEPAGE_ICON_VERSION,
    SLIDE_VERSION,
    PLATFORM_CHOICES, SOURCE_POSITION_DEVICE_TYPE)
from gm_types.gaia import HOMEPAGE_OPERATE_LOCATION as HL
from gm_types.doris import CARD_TYPE
from api.models.slide import Slide, Gadget, ButtonGadget, ZoneLayout, CommunityDeploy, IndextabConfig, HomepageOperate, \
    SlideToDisplaySite, DisplaySite
from api.models import IndexFunction
from api.models import SmallImage
from api.models import City, Province
from api.models import TabOperate, HomepageIcon, HomepageActivity, FestivalHomepageIcon
from api.tool.user_tool import get_user_from_context, get_user_level, get_user_and_payment_info, user_have_payment, \
    new_get_user_and_payment_info
from api.tool.operate_tool import format_operate_query
from api.view.configuration import get_person_slide
from category.models import CategoryPolymer

from rpc.decorators import bind, bind_context, cache_page
from rpc.cache import slide_cache
from rpc.tool.log_tool import info_logger
from rpc.decorators import list_interface
from rpc.tool.error_code import gen, CODES
from statistic.tasks import add_diary_pv
from api.tool.slide_tab_tool import UserTokenCollection
from api.tool.user_tool import filter_user_nick_name
from api.tool.user_tool import is_new_user_local
from api.tool.get_query import get_query_by_usertype_and_location
from utils.version import version_gte, version_lte


@bind("api/slide/list")
@cache_page(120)
@list_interface(offset_name='offset', limit_name='limit', element_model=Slide)
def slide_list(position=SLIDE_POSITION.FIRST, offset=0, limit=10, slide_types=None, display_type=None):
    q = Q()
    if slide_types:
        q &= Q(slide_type__in=slide_types)
    if display_type is not None:
        slide_ids = list(SlideToDisplaySite.objects.filter(
            display_site__display_type=display_type).values_list('slide_id', flat=True))
        q &= Q(id__in=slide_ids)

    data = Slide.query(q, position=position, offset=offset, limit=limit)
    diary_ids = []
    slides = data['slides']
    for slide in slides:
        if slide['slide_type'] == SLIDE_TYPE.DIARY:
            diary_ids.append(slide['diary_id'])

    add_diary_pv.delay(diary_ids)
    return data


# TODO: 迁移至 talos 需要删除
def get_diary_info_for_index(diary_ids, user):
    # api/slide/city_list_diary_ad_v1  todo 7675 已迁移，可删  180502
    from rpc.tool.es_helpers import get_objects_from_queryset_and_pk_list
    from talos.models.diary import Diary
    from social import SocialInfo
    from api.tool.datetime_tool import get_humanize_datetime, get_timestamp_or_none
    from gm_types.gaia import AUTHOR_TYPE, MEMBERSHIP_LEVEL
    from api.tool.user_tool import get_portrait_by_user

    if not diary_ids:
        return []

    diaries = get_objects_from_queryset_and_pk_list(
        Diary.objects.all().prefetch_related("topics"),
        diary_ids,
    )
    result = []

    social_info = None
    if user:
        social_info = SocialInfo(uid=user.id)

    for diary in diaries:
        # TODO: move query out of this for
        diary_author = User.objects.get(pk=diary.user_id)
        diary_data = {
            'diary_id': diary.id,
            'date': get_humanize_datetime(diary.last_modified),
            'last_modified': get_timestamp_or_none(diary.last_modified),
            'title_style_type': diary.title_style_type,
            'view_num': diary.view_num,
            'reply_num': diary.reply_num,
            'vote_num': diary.vote_num,

            'author_type': AUTHOR_TYPE.USER,
            'city': u'中国',  # TODO: delete this
            'user_id': diary.user_id,
            'user_portrait': get_portrait_by_user(diary_author),
            'user_nickname': filter_user_nick_name(diary_author),
            'is_voted': diary.is_voted_by(user),
            'is_following': social_info and social_info.is_following_user(uid=diary.user_id) or False,
            'membership_level': diary_author.userextra and diary_author.userextra.membership_level or MEMBERSHIP_LEVEL.NORMAL,
            'author': {
                'vote_num_gained': diary_author.person.vote_count,
                'topic_num_posted': diary_author.person.topic_count,
            },
            'user_level': get_user_level(diary_author),
        }
        diary_data.update(diary.get_data_from_cache_for_index())  # todo 没有？
        diary_data.update(diary.video_cover())
        result.append(diary_data)
    return result


@bind_context('api/slide/city_list_diary_ad')
def diary_ad(ctx, city_id=None):
    # todo 用api/slide/city_list_diary_ad_v1 ,7675上线后可删
    user = get_user_from_context(ctx)
    q = Q(show_as_diary=True)
    offset = 0
    limit = 10
    position = SLIDE_POSITION.DIARY_LIST_BANNER
    return_ordering = False
    if city_id in WORLD_AREA_TYPE:
        query_region_slide = None
        query_city_slide = None
        query_no_city_slide = q
        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user)
    elif city_id:
        query_region_slide = None
        region = None
        province_id = None
        if position == SLIDE_POSITION.FIRST or position == SLIDE_POSITION.DIARY_LIST_BANNER:
            try:
                city = City.objects.get(id=city_id)
                if getattr(city, 'province'):
                    region = city.province.region
                    province_id = city.province.id
                    if region:
                        query_region_slide = (
                            q & Q(showregion__region=region)
                        )
            except City.DoesNotExist:
                pass

        if province_id:
            # 选北京显示朝阳,选朝阳显示北京
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id) |
                Q(related_slide__city=province_id)
            )
            query_city_slide = q & query
        else:
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id)
            )
            query_city_slide = q & query

        query_no_city_slide = q & Q(related_slide__isnull=True, showregion__region__isnull=True)

        if region:
            query_city_slide &= ~Q(showregion__region=region)

        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user)
    else:
        return []
    diary_ids = [s['diary_id'] for s in data['slides']]
    return get_diary_info_for_index(diary_ids, user)

@bind_context('api/slide/city_list_diary_ad_v1')
def diary_ad_v1(ctx, city_id=None):
    user = get_user_from_context(ctx)
    q = Q(show_as_diary=True)
    offset = 0
    limit = 10
    position = SLIDE_POSITION.DIARY_LIST_BANNER
    return_ordering = False
    if city_id in WORLD_AREA_TYPE:
        query_region_slide = None
        query_city_slide = None
        query_no_city_slide = q
        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user)
    elif city_id:
        query_region_slide = None
        region = None
        province_id = None
        if position == SLIDE_POSITION.FIRST or position == SLIDE_POSITION.DIARY_LIST_BANNER:
            try:
                city = City.objects.get(id=city_id)
                if getattr(city, 'province'):
                    region = city.province.region
                    province_id = city.province.id
                    if region:
                        query_region_slide = (
                            q & Q(showregion__region=region)
                        )
            except City.DoesNotExist:
                pass

        if province_id:
            # 选北京显示朝阳,选朝阳显示北京
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id) |
                Q(related_slide__city=province_id)
            )
            query_city_slide = q & query
        else:
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id)
            )
            query_city_slide = q & query

        query_no_city_slide = q & Q(related_slide__isnull=True, showregion__region__isnull=True)

        if region:
            query_city_slide &= ~Q(showregion__region=region)

        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user)
    else:
        return {'diary_ids': []}

    return {'diary_ids': [s['diary_id'] for s in data['slides']]}


def _get_user_token_slide(limit=10,
                          position=SLIDE_POSITION.FIRST,
                          slide_types=None,
                          city_id=None,
                          location=None,
                          user_type=SLIDE_USER_TYPE.ALL_USER,
                          payment_type=SLIDE_PAYMENT_TYPE.ALL_PAYMENT,
                          display_type=None,
                          show_version=SLIDE_VERSION.V1,
                          platform=SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE,
                          ):
    if not Slide.get_visible(position):
        return {'visible': False, 'slides': []}

    base_query = Q(show_as_diary=False, is_online=True, version=show_version, user_type__in=[user_type, SLIDE_USER_TYPE.ALL_USER],
                   payment_type__in=[payment_type, SLIDE_PAYMENT_TYPE.ALL_PAYMENT])
    if slide_types:
        base_query &= Q(slide_type__in=slide_types)
    if location:
        base_query &= Q(location=location)
    if position:
        base_query &= Q(position=position)
    if display_type is not None:
        slide_ids = list(SlideToDisplaySite.objects.filter(
            display_site__display_type=display_type).values_list('slide_id', flat=True))
        base_query &= Q(id__in=slide_ids)

    region, country_id = (None, None)
    try:
        city = City.objects.get(id=city_id)
        if city.province_id:
            province = Province.objects.select_related('region').get(id=city.province_id)
            region = province.region
            country_id = province.country_id
    except City.DoesNotExist:
        pass
    # 规则如下：
    # 1. 定位在全部地区、无定位、定位在海外，只能看到全部地区的banner(不能看到配置具体城市的banner)
    # 2. 定位在具体城市，可以看到该城市、大区、全部地区的banner
    if not city_id or city_id in WORLD_AREA_TYPE or (region and region.english_name == 'haiwai') or \
            (country_id and country_id != 'china'):
        city_query = Q(related_slide__isnull=True, showregion__region__isnull=True)
    else:
        city_query = Q(related_slide__city=city_id) | Q(related_slide__isnull=True, showregion__region__isnull=True)
        if region:
            city_query |= Q(showregion__region=region)

    now = timezone.now
    query = city_query & base_query
    query &= Q(effect_time__lte=now)
    query &= (Q(end_time__isnull=True) | Q(end_time__gte=now))
    if platform == PLATFORM_CHOICES.IPHONE:
        query &= Q(device_type__in=[SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE, SOURCE_POSITION_DEVICE_TYPE.IOS_DEVICE])
    elif platform == PLATFORM_CHOICES.ANDROID:
        query &= Q(device_type__in=[SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE, SOURCE_POSITION_DEVICE_TYPE.ANDROID])
    else:
        query &= Q(device_type=SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE)
    raw_slides = Slide.objects.filter(query).order_by('ordering').distinct()

    # 获取当前用户类型和支付类型的slide, 优先级满足新用户且无支付>老用户且无支付>新用户>无支付>其他
    collect_banners = UserTokenCollection()
    collect_banners.add_bulk(list(raw_slides))
    collect_result = collect_banners.get_result((user_type, payment_type))

    # 获取带用户标记的banner的dict, token_group_banners = [{}, {}, ...]
    token_group_banners = [s for s in collect_result if s.get('token')]
    token_group_banners = sorted(token_group_banners, key=lambda y: y['ranking'])

    # 获取带用户标记的banner, token_banners = [slide1, slide2, ...]
    token_banners = []
    [token_banners.extend(x['data']) for x in token_group_banners]

    # 如果带用户标记的banner<limit, 从普通的banner中取剩下的部分
    normal_banners = []
    if not len(token_banners) >= limit:
        normal_group_banners = [s for s in collect_result if not s.get('token')]
        [normal_banners.extend(x['data']) for x in normal_group_banners]

    banners_detail = [x.slide_data() for x in (token_banners + normal_banners)]
    Slide.update_banner_diary_topic(banners_detail)

    result = {
        'slides': banners_detail,
        'visible': True
    }
    return result


def _get_previous_slide(ctx,
                        position=SLIDE_POSITION.FIRST,
                        offset=0,
                        limit=10,
                        slide_types=None,
                        city_id=None,
                        return_ordering=False,
                        with_offline=False,
                        location=None,
                        show_version=SLIDE_VERSION.V1
                        ):
    """
    原接口slide_city_list抽出的子函数，除了新轮播图、大图横滑外，获取其他banner仍走该接口
    todo: 该接口待重构...
    :param ctx:
    :param position:
    :param offset:
    :param limit:
    :param slide_types:
    :param city_id:
    :param return_ordering:
    :param with_offline:
    :param location:
    :return:
    """
    user = get_user_from_context(ctx)
    q = Q(show_as_diary=False, version=show_version)
    if slide_types:
        q &= Q(slide_type__in=slide_types)

    if city_id in WORLD_AREA_TYPE:
        query_region_slide = None
        query_city_slide = None
        query_no_city_slide = q
        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user, with_offline=with_offline, location=location)
    elif city_id:
        query_region_slide = None
        region = None
        city = None
        province_id = None
        if position in (SLIDE_POSITION.FIRST, SLIDE_POSITION.DIARY_LIST_BANNER, SLIDE_POSITION.STORY,
                        SLIDE_POSITION.SPECIAL):
            try:
                city = City.objects.get(id=city_id)
                if getattr(city, 'province'):
                    region = city.province.region
                    province_id = city.province.id
                    if region:
                        query_region_slide = (
                            q & Q(showregion__region=region)
                        )
            except City.DoesNotExist:
                pass

        if province_id:
            # 选北京显示朝阳,选朝阳显示北京
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id) |
                Q(related_slide__city=province_id)
            )
            query_city_slide = q & query
        else:
            query = (
                Q(related_slide__city__province_id=city_id) |
                Q(related_slide__city=city_id)
            )
            query_city_slide = q & query

        query_no_city_slide = q & Q(related_slide__isnull=True, showregion__region__isnull=True)

        if region:
            query_city_slide &= ~Q(showregion__region=region)

        data = Slide.slide_city_query(query_region_slide, query_city_slide, query_no_city_slide,
                                      position, offset, limit,
                                      return_ordering, user, with_offline=with_offline, location=location)
    else:
        # 兼容旧的
        data = Slide.query(q, position=position, offset=offset, limit=limit,
                           return_ordering=return_ordering, user=user, with_offline=with_offline)

    if return_ordering and data['slides']:
        result = []
        slides = data['slides']
        ordering = slides[0]['ordering']
        for slide in slides:
            i = slide['ordering']
            if result and i == ordering:
                if slide['banner_id'] > result[-1]['banner_id']:
                    result.pop()
                else:
                    continue
            result.append(slide)
            ordering = i
        data['slides'] = result

    return data


@bind_context("api/slide/city_list")
@list_interface(offset_name='offset', limit_name='limit', element_model=Slide)
def slide_city_list(ctx,
                    position=SLIDE_POSITION.FIRST,
                    offset=0,
                    limit=10,
                    slide_types=None,
                    city_id=None,
                    return_ordering=False,
                    with_offline=False,
                    location=None,
                    platform=None,
                    device_id=None,
                    display_type=None,
                    show_version=SLIDE_VERSION.V1,
                    try_use_special=False,
                    ):
    # 获取首页轮播图、美购首页轮播图等banner
    if position in [SLIDE_POSITION.FIRST, SLIDE_POSITION.SERVICE_HOME, SLIDE_POSITION.SMALL]:
        user = get_user_from_context(ctx)

        params = {'platform': platform, 'device_id': device_id, 'user': user if user else None}

        if city_id and try_use_special and position == SLIDE_POSITION.FIRST:
            user_payment_info = get_user_and_payment_info(**params)
            if user_payment_info["is_new_user"]:
                slides = get_person_slide(city_id, show_version)
                if slides:
                    result = {
                        'slides': slides,
                        'visible': True
                    }
                    return result
                info_logger.info("can't get personal-slide: {}:{}".format(city_id, show_version))

        user_payment_info = new_get_user_and_payment_info(**params)

        user_type = SLIDE_USER_TYPE.OLD_USER
        if user_payment_info and user_payment_info.get('is_new_user'):
            user_type = SLIDE_USER_TYPE.NEW_USER

        payment_type = SLIDE_PAYMENT_TYPE.HAVE_PAYMENT
        if user_payment_info and not user_payment_info.get('have_payment'):
            payment_type = SLIDE_PAYMENT_TYPE.NO_PAYMENT

        cache_key = "{}:{}:{}:{}:{}:{}:{}:{}:{}".format(
            limit, position, slide_types, city_id, location, user_type, payment_type, display_type, show_version
        )
        data = slide_cache.get(cache_key)
        if data:
            return json.loads(data)

        result = _get_user_token_slide(
            limit=limit,
            position=position,
            slide_types=slide_types,
            city_id=city_id,
            location=location,
            user_type=user_type,
            payment_type=payment_type,
            display_type=display_type,
            show_version=show_version,
            platform=platform
        )

        if result.get("slides"):
            slide_cache.set(cache_key, json.dumps(result), ex=60 * 5)

    # 获取体验故事、日记本banner
    else:
        result = _get_previous_slide(
            ctx=ctx,
            position=position,
            offset=offset,
            limit=limit,
            slide_types=slide_types,
            city_id=city_id,
            return_ordering=return_ordering,
            with_offline=with_offline,
            location=location,
            show_version=show_version
        )

    # 增加日记本banner的浏览量
    diary_ids = [s['diary_id'] for s in result['slides'] if s['slide_type'] == SLIDE_TYPE.DIARY]
    add_diary_pv.delay(diary_ids)

    return result


@bind("api/slides")
@bind("api/slide/list_by_platform")
@cache_page(120)
def get_all_slides(platform=u'web'):
    """轮播图
       platform:
    """
    result = []
    if platform == u'web' or platform == u'mobile':
        slides = Slide.objects.filter(effect_time__lte=timezone.now, is_online=True)
        for slide in slides.order_by('ordering'):
            result.append(slide.slide_data())
    return result


@bind("api/slide/get")
def get(slide_id):
    try:
        slide = Slide.object.get(pk=slide_id)
        return slide.slide_data()
    except Slide.DoesNotExist:
        raise gen(CODES.SLIDE_NOT_FOUND)


@bind("api/slide/tab_list")
def get_tab_list():
    try:
        result = IndextabConfig.get()
    except:
        result = []

    return result


@bind('api/smallimage/lastest_n')
@cache_page(120)
@list_interface(limit_name='limit', element_model=SmallImage, element_func_list=[SmallImage.as_dict])
def smallimage(count=10):
    """
    首页小图
    :param count:
    :return:
    """
    sis = SmallImage.objects.filter(
        effect_time__lte=timezone.now).filter(
        is_online=True, type=SMALLIMAGE_TYPE.SMALLIMAGE)
    filter_end_time = Q(end_time__isnull=True) | Q(end_time__gte=timezone.now)
    sis = sis.filter(filter_end_time)
    sis = sis.order_by('ordering', "-created_time")
    return [si.as_dict() for si in sis[:count]]


@bind('api/gadget/get_index')
@cache_page(120)
def get_index_layout(city_id=None):
    res = {}

    #  轮播图 沿用原来的 api/slide/list接口
    res['buttons'] = ButtonGadget.get_buttons(page_type=GADGET_PAGE_TYPE.INDEX,
                                              mask_invisible=True)  # 按钮区
    res['slip_slides'] = SmallImage.get_slip_slides()  # 单排横划区
    if city_id:
        res['gadgets'] = Gadget.get_gadgets(page_type=GADGET_PAGE_TYPE.INDEX, city_id=city_id)  # 固定模板区
    else:
        res['gadgets'] = Gadget.get_gadgets(page_type=GADGET_PAGE_TYPE.INDEX)

    return res


@bind('api/gadget/get_servicehome')
@cache_page(120)
def get_servicehome_layout(city=None, user_id=None, platform=None, device_id=None):
    #  轮播图 用 api/slide/list接口
    res = {}
    try:
        user = User.objects.get(id=user_id)
    except User.DoesNotExist:
        user = None

    new_user_payment_info = new_get_user_and_payment_info(user, platform, device_id)
    if user and new_user_payment_info.get('have_payment'):
        is_payment = SLIDE_PAYMENT_TYPE.HAVE_PAYMENT
    else:
        is_payment = SLIDE_PAYMENT_TYPE.NO_PAYMENT
    user_type = SLIDE_USER_TYPE.NEW_USER if new_user_payment_info.get('is_new_user') else SLIDE_USER_TYPE.OLD_USER
    res['gadgets'] = Gadget.get_gadgets(page_type=GADGET_PAGE_TYPE.SERVICE_HOME, city_id=city, user_type=user_type, platform=platform, payment_type=is_payment)  # 固定模板区

    return res


@bind('api/gadget/get_communityhome')
@cache_page(120)
def get_communityhome_layout():
    res = {}
    res['buttons'] = ButtonGadget.get_buttons(page_type=GADGET_PAGE_TYPE.COMMUNITY_HOME,
                                              mask_invisible=True)  # 按钮区
    res['gadgets'] = Gadget.get_gadgets(page_type=GADGET_PAGE_TYPE.COMMUNITY_HOME)  # 固定模板区
    hot_tags = ZoneLayout.get_zone_layout()
    res['hot_tags'] = {
        'visible': hot_tags['zone_visible'],
        'hot_in_24hours': hot_tags['hot_in_24hours'],
    }
    community_deploy = CommunityDeploy.get_community_deploy()
    res['community_deploy'] = community_deploy
    return res


@bind('api/slide/get_related_type_info')
@cache_page(120)
def get_related_type_info(banner_id):
    # 首页精选中banner中的diary及topic点赞时，首先返回该banner中点赞对应的具体diary或topic
    try:
        _s = Slide.objects.get(pk=banner_id)
        if _s.topic_id:
            return {
                'vote_to': 'topic',
                'id': _s.topic_id,
            }
        elif _s.diary_id:
            return {
                'vote_to': 'diary',
                'id': _s.diary_id,
            }

        gen(CODES.OPERATION_NOT_SUPPORTED)
    except Slide.DoesNotExist:
        raise gen(CODES.SLIDE_NOT_FOUND)


@bind('api/slide/big_image_slider')
@cache_page(120)
def get_big_image_slider(start_num, count, location=SLIDE_LOCATION.FIRST):
    """
    todo: 等待策略改动，修改取大图横滑的规则
    :param start_num:
    :param count:
    :param location:
    :return:
    """
    slides = []

    queryset = Slide.objects.filter(location=location)[start_num: start_num + count]
    for slide in queryset:
        slides.append({
            'name': slide.title,
            'icon': slide.slide_img,
            'url': slide.url
        })
    return slides


@bind('api/index/v6/templates')
@cache_page(120)
def get_index_templates(city_id=None, platform=None, device_id=None, user_id=None):
    """
    新版首页的固定模版
    :param city_id:
    :return:
    """
    filter = {'page_type': GADGET_PAGE_TYPE.INDEX, 'city_id': city_id, 'show_in_v6': True}
    try:
        user = User.objects.get(id=user_id)
    except User.DoesNotExist:
        user = None

    new_user_payment_info = new_get_user_and_payment_info(user, platform, device_id)
    if user and new_user_payment_info.get('have_payment'):
        is_payment = SLIDE_PAYMENT_TYPE.HAVE_PAYMENT
    else:
        is_payment = SLIDE_PAYMENT_TYPE.NO_PAYMENT
    user_type = SLIDE_USER_TYPE.NEW_USER if new_user_payment_info.get('is_new_user') else SLIDE_USER_TYPE.OLD_USER
    filter['user_type'] = user_type
    filter['payment_type'] = is_payment
    filter['platform'] = platform
    return Gadget.get_gadgets(**filter)  # 固定模板区


def _format_homepage_operate_query(ctx, city_id=None, platform=None, device_id=None):
    user = get_user_from_context(ctx)
    return format_operate_query(user=user, city_id=city_id, platform=platform, device_id=device_id)


@bind_context('api/homepage/operate_banner')
def get_homepage_operate_banner(ctx, location, count=5, city_id=None, platform=None, device_id=None):
    params = {
        'ctx': ctx,
        'city_id': city_id,
        'platform': platform,
        'device_id': device_id
    }
    base_query = _format_homepage_operate_query(**params)
    base_query_set = HomepageOperate.objects.filter(base_query).order_by('rank', '-id')

    if isinstance(location, list):
        operate_banner_a = list(base_query_set.filter(location=HL.OPERATE_A)[:count])
        operate_banner_b = base_query_set.filter(location=HL.OPERATE_B).first()
        queryset = operate_banner_a
        if operate_banner_b:
            queryset.append(operate_banner_b)
    else:
        queryset = base_query_set.filter(location=location)[:count]

    result = [banner.banner_data() for banner in queryset]
    return filter(lambda r: r['entity_id'] is not None, result)


# 置顶配置位规则
_tab_map = {
    TAB_TYPES_NEW.GOSSIP: [CARD_TYPE.QUESTION, CARD_TYPE.ANSWER],
    TAB_TYPES_NEW.BIG_SHOT: [CARD_TYPE.QUESTION, CARD_TYPE.ANSWER],
    TAB_TYPES_NEW.HOME_VIDEO: [CARD_TYPE.DIARY],
    TAB_TYPES_NEW.CHOICE: [CARD_TYPE.DIARY, CARD_TYPE.ARTICLE, CARD_TYPE.ANSWER, CARD_TYPE.QUESTION],
}

@bind('api/homepage/operate_tab')
@cache_page(60 * 5)
def get_homepage_operate_tag(tab_type):
    top_num = 1 if tab_type == TAB_TYPES_NEW.CHOICE else 2
    objs = TabOperate.objects.filter(tab=tab_type,
                                     is_online=True,
                                     card_type__in=_tab_map[tab_type]
                                     ).order_by('rank', '-id')
    result = {}
    for rank, obj in enumerate(objs[:top_num]):
        if not result.get(obj.card_type):
            result[obj.card_type] = []
        result[obj.card_type].append((obj.card_id, rank))
    return result


@bind_context('api/homepage/icon')
def get_homepage_icon(ctx, city_id=None, platform=None, device_id=None, polymer_ids=[],
                      icon_version=HOME_PAGE_ICON_VERSION.V1, special_icon_version=FESTIVAL_HOMEPAGE_ICON_VERSION.V1,
                      app_version=None, new_img=False):
    """

    :param ctx:
    :param city_id:
    :param platform:
    :param device_id:
    :param polymer_ids: 策略给出的自动排序后的品类聚合页id
    :param icon_version: 首页icon版本
    :param special_icon_version: 首页icon特殊信息版本
    :return:
    """
    result = {
        "homepage_icon": [],
        "index_background": {
            "background_img": "",
            "font_color": "1",
        }
    }
    user = get_user_from_context(ctx)
    polymer_ids = [str(id) for id in polymer_ids]
    AUTO_RANK_NUM_FLAG = 999999
    params = {
            'user': user,
            'city_id': city_id,
            'platform': platform,
            'device_id': device_id
        }

    # 筛选出用户可以看到的所有的icon， 可以保证包含了策略给出的icon id。
    query = get_query_by_usertype_and_location(**params)
    icon_query = query & Q(version=icon_version)
    icons = list(HomepageIcon.objects.filter(icon_query).order_by('rank', '-id'))
    if icons:
        def sort_func(x):
            # 按照polymer_ids顺序排序，
            if x in polymer_ids:
                return polymer_ids.index(x)
            else:
                return len(polymer_ids)

        # 筛选出可以使用的自动排序icon
        auto_icons, extend_auto_icons = [], []
        homepage_icon_ids_records = set()
        for item in icons:
            if item.rank == AUTO_RANK_NUM_FLAG:
                if item.jump_type == HOMEPAGE_OPERATE_TYPE.CATEGORY and item.jump in polymer_ids:
                    auto_icons.append(item)
                else:
                    #获取属于个性化推荐但是没被推荐的icon
                    extend_auto_icons.append(item)
                homepage_icon_ids_records.add(item.id)
        # auto_icons 为可用的补位icon
        auto_icons = sorted(auto_icons, key=lambda k: sort_func(k.jump))
        #将属于个性化推荐，但是没被推荐的icon放在被推荐的icon的后面
        auto_icons.extend(extend_auto_icons)
        ans_icons = [None] * settings.HOMEPAGE_ICON_CNT
        #固定位置icon放置
        for obj in icons:
            if obj.id not in homepage_icon_ids_records:
                if obj.rank <= settings.HOMEPAGE_ICON_CNT:
                    ans_icons[obj.rank-1] = obj
                    homepage_icon_ids_records.add(obj.id)
        #个性化icon补位
        i = j = 0
        while i < settings.HOMEPAGE_ICON_CNT and j < len(auto_icons):
            if ans_icons[i]:
                i += 1
                continue
            else:
                ans_icons[i] = auto_icons[j]
                i += 1
                j += 1
        result["homepage_icon"] = [icon.icon_data(new_img=new_img) for icon in ans_icons if icon]
    festival_query = query & Q(version=special_icon_version)
    festival_imgs = FestivalHomepageIcon.objects.filter(festival_query).order_by('-id')

    festival_img = None
    if app_version:
        for item in festival_imgs:
            if (
                (item.min_version == '' and item.max_version == '') or
                (item.min_version == '' and version_lte(app_version, item.max_version)) or
                (version_gte(app_version, item.min_version) and item.max_version == '') or
                (version_gte(app_version, item.min_version) and version_lte(app_version, item.max_version))
            ):
                festival_img = item
                break

    if festival_img:
        festival_info = festival_img.img_data()
        festival_images = festival_info.get("festival_img", [])

        for icon_info, festival_image in list(zip(result["homepage_icon"][:len(festival_images)], festival_images)):
            icon_info["image"] = festival_image

        result["index_background"] = {
            "background_img": festival_info['background_img'],
            "font_color": festival_info['font_color'],
        }

    return result


@bind_context('api/homepage/activity')
def get_homepage_activity(ctx, city_id=None, platform=None, device_id=None):
    user = get_user_from_context(ctx)
    params = {
        'user': user,
        'city_id': city_id,
        'platform': platform,
        'device_id': device_id
    }
    query = get_query_by_usertype_and_location(**params)
    activity = HomepageActivity.objects.filter(query).order_by('-id').first()
    if activity:
        activity = activity.data()
    else:
        activity = {
            "icon_image": "",
            "jump_type": "",
            "jump": "",
            "id": None,
        }
    return {"homepage_activity": activity}


@bind_context('api/homepage/category_polymer_operation')
def get_homepage_activity(ctx, category_polymer_id=None):
    """
    判断品类聚合页有没有关联一级运营id
    @param: category_polymer_id 品类聚合id
    """
    res = CategoryPolymer.objects.filter(id=category_polymer_id).first()
    return True if res.operation_level_one_id else False


@bind_context('api/homepage/category_polymer_operation/by_ids')
def get_homepage_icon_by_ids(ctx, category_polymer_ids=None):
    """
    判断品类聚合页有没有关联一级运营id批量查询接口
    @param: category_polymer_id 品类聚合id
    """
    res = CategoryPolymer.objects.filter(id__in=category_polymer_ids)
    category_polymer_id_res = {str(item.id): True if item.operation_level_one_id else False for item in res}
    return category_polymer_id_res
