# -*- coding:utf-8 -*-
"""文章页面"""

from kyger.utility import numeric


class Article(object):
    """文章调用"""
    __page = 0  # 当前页
    __total_page = 0  # 总页数
    __total_rows = 0  # 总记录数

    # 构造函数
    def __init__(self, db=None, kg=None):
        # 数据库
        from kyger.db import MySQL
        self.db = db if db else MySQL()  # 数据库操作对象
        self.kg = kg  # 全局变量
        self.__limit = ''

    def list_page(self, *args, **kwargs):
        """
        分页获取文章信息，参数同list。
        :return:{
            'list':          # 分页的当前页文章数据
            'page_html':     # 分页的html模板
            'page_data':     # 分页的数据：当前页、总页数、总记录数
        }
        """
        # page和row的数据
        self.__page = numeric(self.kg['get'].get('page', 1), 1)  # 当前页
        if 'row' in kwargs:
            row = kwargs['row']  # 在kwargs里
        elif len(args) > 2:
            row = args[1]  # 在args里
        else:
            row = 10  # 默认10

        # 获取文章数据
        data = self.list(*args, **kwargs)
        # 分页模板合成
        web_url = self.kg['server'].get('WEB_URL')
        from kyger.common import page_tpl
        page_html = page_tpl(self.__page, self.__total_page, row, web_url)  # 获取分页模板
        # self.__total_rows = self.db.total_rows  # 总记录数
        # self.__total_page = self.db.total_page  # 总页数
        return {
            'list': data,
            'page_html': page_html,
            'page_data': {'page': self.__page, 'total_page': self.__total_page, 'total_rows': self.__total_rows}
        }

    def list(self, sort=0, row=10, recom=0, category=0, start=0, picture=0, word='', published=1, audit=1,
             recycle=1, comment=0, date='%Y-%m-%d', field=0):
        """
        获取文章数据
        :param sort: [int] 排序，,0ID降序，1ID升序，2日期降序，3日期升序，4浏览数降序，5浏览数升序，6评论数降序，7评论数升序，8自定义。缺省值0
        :param row: [int] 分页时为每页要显示的数量，不分页时为调用的总记录数。缺省值为 10
        :param recom: [int] 是否推荐，0调用全部，1只调用推荐，2只调用不推荐。缺省值为0
        :param category: [int] 调用栏目id，0调用全部，其他为要调用的栏目id。缺省值0
        :param start: [int] 不分页时，从第几天数据开始调用，分页时无效。缺省值0
        :param picture: [int] 是否调用带有图片的内容，0调用全部，1调用有图片数据，2调用无图数据。缺省值0
        :param word: [str] 搜索的关键字。
        :param published: [int] 是否调用已发布的内容，0调用全部，1调用已发布，2调用草稿。缺省值0
        :param audit: [int] 是否调用已审核的内容，0调用全部，1调用审核，2调用未审核。缺省值0
        :param recycle: [int] 是否调用回收站的内容，0调用全部，1调用正常，2调用回收站。缺省值0
        :param comment: [int] 是否调用可评论内容，0调用全部，1调用可评论，2调用不可评论。缺省值0
        :param date: [str] 日期格式化：
                                %y 两位数的年份表示（00-99）  %Y 四位数的年份表示（000-9999）  %m 月份（01-12）  %d 日，月内中的一天（0-31）
                                %H 24小时制小时数（0-23）  %I 12小时制小时数（01-12）  %M 分钟数（00=59）  %S 秒（00-59）
                                %a 本地简化星期名称  %A 本地完整星期名称 %b 本地简化的月份名称, 英文  %B 本地完整的月份名称, 英文
                                %c 本地相应的日期表示和时间表示  %j 年内的一天（001-366）  %p 本地A.M.或P.M.的等价符  %U 一年中的星期数（00-53）星期天为星期的开始（第n周）
                                %w 星期（0-6），星期天为星期的开始  %W 一年中的星期数（00-53）星期一为星期的开始（第n周）   %x 本地相应的日期表示
                                %X 本地相应的时间表示  %Z 当前时区的名称  %% %号本身
        :param field: [int|list] 为0时查询默认字段，为列表时查询列表内包含的字段，例：['id', 'title', 'author']。缺省值0
        :return:{
        }
        """
        # where条件的处理
        word_sql = "&&(`title` like '%%%s%%' or `content` like '%%%s%%')" % (word, word) if word else ""
        category_sql = "&& `category` rlike '[\[|, ]%d[\]|,]'" % category if category else ""
        # 推荐
        if recom == 1:
            recom_sql = "&& `recom` = 1"  # 推荐
        elif recom == 2:
            recom_sql = "&& `recom` = 0"  # 不推荐
        else:
            recom_sql = ""
        # 图片
        if picture == 1:
            picture_sql = "&& `picture` like '[\"%%\"]'"  # 有图片
        elif picture == 2:
            picture_sql = "&& `picture` like '[]'"  # 无图片
        else:
            picture_sql = ""
        # 发布
        if published == 1:
            published_sql = "&& `published` = 1"  # 已发布
        elif published == 2:
            published_sql = "&& `published` = 0"  # 草稿
        else:
            published_sql = ""
        # 审核
        if audit == 1:
            audit_sql = "&& `audit` = 1"  # 通过审核
        elif audit == 2:
            audit_sql = "&& `audit` = 0"  # 未通过审核
        else:
            audit_sql = ""
        # 回收站
        recycle_sql = "&& `recycle` = 0" if recycle == 1 else "&& `recycle` = 1"  # 回收站
        # 评论
        if comment == 1:
            comment_sql = "&& `comment` = 1"  # 允许评论
        elif comment == 2:comment_sql = "&& `comment` = 0"  # 不允许评论
        else:comment_sql = ""
        # 拼接where参数
        where = "webid=%s %s %s %s %s %s %s %s %s" % \
                (self.kg['web']['id'], recycle_sql, category_sql, word_sql, recom_sql, picture_sql, published_sql, audit_sql,
                 comment_sql)
        # sort
        sort_param = {
            0: '`id` DESC',  # 内容ID降序
            1: '`id` ASC',  # 内容ID升序
            2: '`pushtime` DESC',  # 发布时间降序
            3: '`pushtime` ASC',  # 发布时间升序
            4: '`click` DESC',  # 点击次数降序
            5: '`click` ASC',  # 点击次数升序
            6: '`commenttotal` DESC',  # 评论人数降序
            7: '`commenttotal` ASC',  # 评论人数升序
            8: '`sort` DESC,`addtime` DESC',  # 按自定义字段降序优先，其次按发布日期降序
            9: '`title` like "%%%s%%" DESC, `content` like "%%%s%%" DESC'
        }
        if word: sort = 9  # 如果进行搜索使用标题和内容排序

        # field字段
        field = ', '.join(field) if isinstance(field, list) else '*'

        # limit
        if self.__page:
            # 子查询获取开始id
            num1 = row * (self.__page - 1) + 1 if (self.__page - 1) else 1
            start_id = self.db.list(
                table='article',
                field='id',
                where=where,
                order=sort_param[sort],
                page=num1,
                limit=1,
                shift=1
            )
            # 总页数
            self.__total_page = (self.db.total_rows // row) + 1 if self.db.total_rows % row else self.db.total_rows // row
            self.__total_rows = self.db.total_rows  # 总记录数
            if self.__page > self.__total_page:
                self.__page = (self.db.total_rows // row) + 1 if self.db.total_rows % row else self.db.total_rows // row
                num = 1 if self.db.total_page // row else '0,1'
                start_id = self.db.list(
                    table='article',
                    field='id',
                    where=where,
                    order=sort_param[sort],
                    page=row * (self.db.total_page // row),
                    limit=num,
                    shift=1
                )
            if start_id:
                where_sql = where + '&& id >= %d' % start_id['id'] if sort else where + '&& id <= %d' % start_id['id']
                data = self.db.list(  # 从开始id取row条数据
                    table='article',
                    field=field,
                    where=where_sql,
                    order=sort_param[sort],
                    limit='0, %d' % row
                )
            else:
                data = []

        else:
            data = self.db.list(
                table='article',
                field=field,
                where=where,
                order=sort_param[sort],
                limit='%d, %d' % (start, row)
            )

        data = self.data_format(data, date) if data else []  # 数据整形
        return data

    def single(self, articleid, date='%Y-%m-%d', frontend=0):
        """
        根据单个id获取数据
        :param articleid: [int] 要获取数据的ID
        :param date: [str] 日期格式化：
                                %y 两位数的年份表示（00-99）  %Y 四位数的年份表示（000-9999）  %m 月份（01-12）  %d 日，月内中的一天（0-31）
                                %H 24小时制小时数（0-23）  %I 12小时制小时数（01-12）  %M 分钟数（00=59）  %S 秒（00-59）
                                %a 本地简化星期名称  %A 本地完整星期名称 %b 本地简化的月份名称, 英文  %B 本地完整的月份名称, 英文
                                %c 本地相应的日期表示和时间表示  %j 年内的一天（001-366）  %p 本地A.M.或P.M.的等价符  %U 一年中的星期数（00-53）星期天为星期的开始（第n周）
                                %w 星期（0-6），星期天为星期的开始  %W 一年中的星期数（00-53）星期一为星期的开始（第n周）   %x 本地相应的日期表示
                                %X 本地相应的时间表示  %Z 当前时区的名称  %% %号本身
        :param frontend: [int] 为0时不限制条件，为1时限制回收站、审核、发布、发布时间。缺省值0
        :return: [list{}] 返回查询到的单条数据
        """
        # 转换成数值
        articleid = numeric(articleid, 0)

        # where
        if frontend:
            where = 'webid=%s && id=%s && recycle=0 && audit=1 && published=1 && pushtime < %s' % (self.kg['web']['id'], articleid, int(self.kg['run_start_time'][1]))
        else:
            where = 'webid=%s && id=%s' % (self.kg['web']['id'], articleid)

        # 数据库查询与数据整形
        data = self.db.list(table='article', where=where, shift=1)

        if data:
            data = self.data_format(data, date)
        return data

    def data_format(self, data, date_format):
        """
        将数据进行整形
        :param data: [list{}] 从数据库查出的数据
        :param date_format: [str] 日期格式化：
                                %y 两位数的年份表示（00-99）  %Y 四位数的年份表示（000-9999）  %m 月份（01-12）  %d 日，月内中的一天（0-31）
                                %H 24小时制小时数（0-23）  %I 12小时制小时数（01-12）  %M 分钟数（00=59）  %S 秒（00-59）
                                %a 本地简化星期名称  %A 本地完整星期名称 %b 本地简化的月份名称, 英文  %B 本地完整的月份名称, 英文
                                %c 本地相应的日期表示和时间表示  %j 年内的一天（001-366）  %p 本地A.M.或P.M.的等价符  %U 一年中的星期数（00-53）星期天为星期的开始（第n周）
                                %w 星期（0-6），星期天为星期的开始  %W 一年中的星期数（00-53）星期一为星期的开始（第n周）   %x 本地相应的日期表示
                                %X 本地相应的时间表示  %Z 当前时区的名称  %% %号本身
        :return: [list{}] 将整形过后的数据返回
        """
        from kyger.utility import json2dict, date, str_replace, nl2br, str_cutting, strip_tags
        # 获取栏目标题
        category_title = self.db.list(table='category', field='id, title')
        res = {}
        for row in category_title:
            res[row['id']] = row
        if isinstance(data, dict):
            data_type = 'dict'
            data = [data]
        else:
            data_type = 'list'

        # 获取评论数据
        article_id_list = []
        for var in data:
            article_id_list.append(str(var['id']))
        comment_count_dict = {}
        if article_id_list:
            comment_counts = self.db.list(
                table="comment",
                field="count(*), aid",
                where='audit=1 && webid=%s && type=1 && aid in (%s) group by aid' % (self.kg['web']['id'], ','.join(article_id_list))
            )
            for comment_count in comment_counts:
                comment_count_dict[comment_count['aid']] = comment_count['count(*)']

        # 数据整形
        if isinstance(data, list):
            for i in data:
                # 更新评论总数
                comment_count = comment_count_dict.get(i['id'], 0)
                i['comment_count'] = comment_count

                # 简要描述
                if i.get('description', ''):
                    i['summary'] = str_cutting(i['description'], 170)
                else:
                    i['summary'] = str_cutting(strip_tags(i['content']), 170)

                # 标题裁切
                i['cut_title'] = str_cutting(i['title'], 60)

                # 图片url json转换
                i['url'] = 'article?id=%s' % i['id']
                if 'picture' in i: i['picture'] = json2dict(i['picture'])

                # 栏目列表json转换
                i['authority'] = json2dict(i['authority'])
                if 'category' in i:
                    i['category'] = json2dict(i['category'])
                    # 栏目标题和添加
                    cid = i['category'][len(i['category']) - 1]
                    i['category_title'] = res[cid]['title']

                # 时间格式显示
                if 'addtime' in i:
                    i['addtime'] = date(i['addtime'], format=date_format)
                if 'pushtime' in i:
                    i['pushtime'] = date(i['pushtime'], format='%Y-%m-%d %H:%M')

                # SEO处理
                if not i['keyword']:
                    i['keyword'] = i['tag'] if i['tag'] else i['title']  # 关键字
                if not i['introduction']: i['introduction'] = str_cutting(strip_tags(i['content']), 508)  # seo描述

        if data_type == 'dict': data = data[0]
        return data
