#!/usr/bin/env python
# -*- coding: utf_8 -*-
import traceback
import logging

from pony.orm import *
from pony.orm.serialization import to_json
from pony.flask import Pony

logger = logging.getLogger(__name__)


class FullStackDB(object):

    def __init__(self):
        super(FullStackDB, self).__init__()
        self._db = Database()

    @property
    def db(self):
        return self._db

    def __call__(self, app=None, drop_tables=[]):
        if app:
            Pony(app)
            self.db.bind(**app.config['PONY'])
            for name in drop_tables:
                # 删除表，演示实体声明时用于快速清除旧表
                self.db.drop_table(name, if_exists=True, with_all_data=True)
            self.db.generate_mapping(create_tables=True)

    def get(self, table, **kwargs):
        '''
        得到条目
        '''
        with db_session():
            item = table.get(**kwargs)
            return item

    def add(self, table, **kwargs):
        '''
        增加条目
        :param table: 操作的数据表
        :param  **kwargs: 新增条目的属性和值
        '''
        with db_session():
            item = table(**kwargs)
            commit()
            return item

    def delete(self, table, **kwargs):
        '''
        删除条目
        :param table: 操作的数据表
        :param **kwargs:  删除条目的属性和值
        '''
        with db_session():
            target = table.get(**kwargs)
            if target:
                target.delete()
                commit()
                return True
            else:
                return False

    def update(self, table, filters, **kwargs):
        '''
        :param item: 需要更新的条目,如 User[1]
        :param **kwargs: 更新后条目的属性和值
        '''
        with db_session():
            item = table.get(**filters)
            if item:
                for key, value in kwargs.items():
                    if value != None and hasattr(item, key):
                        setattr(item, key, value)
                commit()
                return item
            else:
                return False

    def display(self, table):
        '''
        展示表格的所有条目信息
        :param table: 操作的数据表
        :return 成功则返回一个包含所有条目的列表 | 失败返回False
        '''
        with db_session():
            items = select(item for item in table)[:]
            items.show()
            return items

    def select(self, table, **kwargs):
        with db_session():
            return table.select(**kwargs)

    def pagination(self, table, order, pagenum=1, pagesize=10, **kwargs):
        if not isinstance(pagenum, int):
            pagenum = int(pagenum)
        if not isinstance(pagesize, int):
            pagesize = int(pagesize)
        with db_session():
            return table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)

    def pagination_dict(self, table, order, pagenum=1, pagesize=10, **kwargs):
        if not isinstance(pagenum, int):
            pagenum = int(pagenum)
        if not isinstance(pagesize, int):
            pagesize = int(pagesize)
        with db_session():
            result = table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)
            temp = []
            for item in result:
                t = item.to_dict(with_collections=True, related_objects=True)
                for key in t:
                    if isinstance(t[key], self.db.Entity):
                        t[key] = t[key].to_dict()
                temp.append(t)
            return temp

    def count(self, table, **kwargs):
        with db_session():
            return table.select().where(**kwargs).count()

fullStackDB = FullStackDB()
