#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
__title__ = '新圈子-知识tab过滤  http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=5478006&focusedCommentId=5479145#comment-5479145'
__author__ = 'xierong@gmei.com'
__mtime__ = '18/4/2'
'''

from django.conf import settings
from django.db.models import Q
import random
from search.models import MixIndex, MixIndexTag
from qa.models.answer import Answer
from talos.models.topic import Article

from gm_types.error import ERROR
from gm_types.gaia import INDEX_CARD_TYPE, KNOWLEDGE_ORDER_TYPE
from gm_rpcd.all import bind
from utils.rpc import gen, logging_exception


@bind("diary/filter_answer_and_column")
def filter_answer_and_column(sort_type=KNOWLEDGE_ORDER_TYPE.LASTEST, offset=None, size=10, tags=None, filters={}):
    def get_random_sample(old_sorted_list=None, out_lst_count=0):
        '''
        随机取列表的一半，幷按原列表排序返回
        :param old_sorted_list: 待随机获取的列表
        :param out_lst_count: 获取的数量
        :return: 
        '''
        old_sorted_list = old_sorted_list or []
        if len(old_sorted_list) < out_lst_count:
            return old_sorted_list

        old_list_index_dict = {k: i for i, k in enumerate(old_sorted_list)}
        sliced_article_ids = random.sample(old_sorted_list, out_lst_count)
        return sorted(sliced_article_ids, key=lambda x: old_list_index_dict[x])  # 最后list 按原有排序

    if not tags or not isinstance(tags, list):
        return gen(ERROR.PARAMS_INCOMPLETE)

    if not sort_type in KNOWLEDGE_ORDER_TYPE:
        return gen(ERROR.OPERATION_NOT_SUPPORTED)

    tags = tags or []
    size = min(size, settings.COUNT_LIMIT)
    re_data = {'data': [], 'offset': offset}

    # 根据不同排序，组装数据结构
    tag_related_ids = MixIndexTag.objects.filter(tag_id__in=tags).values_list('mix_index', flat=True).distinct()

    tag_related_data_length = tag_related_ids.count()
    if tag_related_data_length <= 0:
        return re_data

    data_queryset = MixIndex.objects.filter(id__in=tag_related_ids)

    final_out_put_list = []
    answer_id_list, article_id_list = [], []
    if sort_type == KNOWLEDGE_ORDER_TYPE.LASTEST:
        try:
            offset = 0 if not offset else int(offset)
        except:
            logging_exception()
            offset = 0
        if offset > data_queryset.count():
            return re_data
        data_queryset = data_queryset.order_by('-original_create_time')[offset:offset + size]
        final_out_put_list = [q for q in data_queryset]
        re_data['offset'] = offset + size

    elif sort_type == KNOWLEDGE_ORDER_TYPE.BEST:
        # 固定的格式 4回答-1专栏-4回答-1专栏
        mix_data_size = 5
        insert_index = mix_data_size - 1

        offset = '0_0' if not offset else offset  # answer-offset _ article-offset
        offset_lst = offset.split('_')
        if len(offset_lst) < 2:
            offset_lst = ['0', '0']

        size *= 2   # 结果20取10，下拉刷新变化

        multi_x = int(size / mix_data_size)
        remainder = size % mix_data_size

        answer_start = int(offset_lst[0])
        answer_end = answer_start + insert_index * multi_x + remainder

        column_start = int(offset_lst[1])
        column_end = column_start + size - (answer_end - answer_start)

        re_data['offset'] = '{0}_{1}'.format(answer_end, column_end)  # need to give it bc to front
        # get answer
        final_answer = data_queryset.filter(original_type=INDEX_CARD_TYPE.ANSWER,
                                            answer_is_recommend=True).order_by('-answer_score')[answer_start:answer_end]
        answer_to_sort_lst = [ans.original_id for ans in final_answer]
        final_answer_dict = {a.original_id: a for a in final_answer}
        answer_id_list = get_random_sample(answer_to_sort_lst, int((answer_end-answer_start)/2))    # 随机取值，幷输出按原有排序
        final_out_put_list = [final_answer_dict.get(ans) for ans in answer_id_list]
        # get article
        final_column = data_queryset.filter(original_type=INDEX_CARD_TYPE.ARTICLE,
                                            ).order_by('-original_create_time')[column_start:column_end]
        column_to_sort_lst = [f.original_id for f in final_column]

        final_column_dict = {c.original_id: c for c in final_column}
        article_id_list = get_random_sample(column_to_sort_lst, int((column_end-column_start)/2))
        final_column = [final_column_dict.get(c) for c in article_id_list]
        for item in final_column:
            final_out_put_list.insert(insert_index, item)
            insert_index += (mix_data_size - 1) + 1    # 1为自身刚insert的

    # 组装数据 #
    if not answer_id_list:
        answer_id_list = [item.original_id for item in final_out_put_list if item.original_type == INDEX_CARD_TYPE.ANSWER]
    if not article_id_list:
        article_id_list = [item.original_id for item in final_out_put_list if item.original_type == INDEX_CARD_TYPE.ARTICLE]

    answer_query = Q(id__in=answer_id_list) & Q(is_online=True)
    if filters.get("levels", []) and isinstance(filters.get("levels", []), list):
        answer_query &= Q(level__in=filters.get("levels"))
    answer_queryset = Answer.objects.filter(answer_query)
    answer_query_dict = {ans.id: ans for ans in answer_queryset}
    article_queryset = Article.objects.filter(id__in=article_id_list, is_online=True)
    article_query_dict = {art.id: art for art in article_queryset}

    for item in final_out_put_list:
        if item.original_type == INDEX_CARD_TYPE.ANSWER:
            if answer_query_dict.get(item.original_id):  # 以免数据同步不及时
                insert_da = answer_query_dict.get(item.original_id).data_for_list()
                insert_da.update({'describe': u'回答了问题'})
                re_data['data'].append({
                    'type': INDEX_CARD_TYPE.ANSWER,
                    'id': item.original_id,
                    'answer': insert_da
                })
        elif item.original_type == INDEX_CARD_TYPE.ARTICLE:
            if article_query_dict.get(item.original_id):
                final_article_data = article_query_dict.get(item.original_id).data
                final_article_data.update({'describe': u'发表了专栏'})
                re_data['data'].append({
                    'type': INDEX_CARD_TYPE.ARTICLE,
                    'id': item.original_id,
                    'article': final_article_data,
                })

    return re_data
