# coding=utf8
from __future__ import unicode_literals, absolute_import, print_function
import pkgutil
import inspect

from .types import *

from .tag import *
from .area import *
from .assist import *
from .channel import *
from .bodypart import *
from .bodypartsubitem import *
from .user import *
from .user_activity import *
from .itemwiki import *
from .hospital import *
from .doctor import *
from .service import *
from .order import *
from .slide import *
from .coupon import *
from .special import *
from .pushtask import *
from .pushtask2 import *
from .message import *
from .campaign import *
from .audit import *
from .person import *
from .bigsale import *
from .game import *
from .feedback import *
from .reservation import *
from .shopcart import *
from .settlement import *
from . import bigsale
from .servicehome import *
from .activity import *
from .recommend_doctor import *
from .share import *
from .business_channel import *
from .advertise import *
from .alipayaccout import *
from .share import *
from .updatepop import *
from .zone import *
from .push import *
from .city import *
from .industrynews import *
from .operateteam import *
from .phoneservice import *
from .advertise_management import *
from .gmhome import *
from .recommenduserattention import *
from .shortmessagesend import *
from .tickets import *
from .smart_rank import *
from .fenxiao import *
from .vote import *
from .seo import *
from .doctorgroup import *
from .servicecomment import *
from .user_home_page import *
from .doctor_intelligence import *
from .budan import *
from .watermark import *
from .pos import *
from .multitopic import *
from .report import *
from .device import *
from .wordrel import *
from .statistic import *
# don't put your imports bellow this line
from .others import *
from .ka import *
from .photo import *
from .diaryspread import *
from .feed import *
from .college import *
from .bd_transfer import *
from .groupbuy import *
from .variety_vote import *
from .sign_activity import *
from .user_change_log import UserChangeLog
from .activity_young_doctor import *
from .sign_v2 import *
from .face import *
from .beauty_topic import *
from .search_hot_words import *
from .pushtask2 import *
from .non_business import *
from .phone_protect import *
from .business import *
from .market import *
from .commodity_info import *
from .push_authorization import *
from .hot import *

"""
    Warning!!!
    Warning!!!
    Warning!!!
    使用此方法会影响读取效率:
    读写隐藏后的字段(对其他字段无影响, 使用_get_full_field_content_也无影响)需要耗时25ms左右(每次)
    如果读写隐藏字段频繁, 不建议使用此方法

    hide_sensitive_field使用方法:
    传入需要隐藏字段所在的Model和隐藏字段的字段名
    提供一个toggle_function和hide_function
    toggle_function即为触发隐藏字段的条件
    hide_function即为如何隐藏字段

    _get_full_field_content_为获取隐藏字段的完整信息

    example:

    hide_sensitive_field(User, 'username', toggle_function, hide_funcion)
    u = User(username = '12345678901')
    u.save()
    u.username  # 12***67890*
    u._get_full_field_content_('username')  # 12345678901
"""

def get_gaia_packages():
    """
    获取gaia top module 名字
    """
    return [m[1] for m in pkgutil.iter_modules(['.']) if m[2]]


def caller_name(skip=2):
    """Get a name of a caller in the format module.class.method

       `skip` specifies how many levels of stack to skip while getting caller
       name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.

       An empty string is returned if skipped levels exceed stack height
    """
    stack = inspect.stack()
    start = 0 + skip
    if len(stack) < start + 1:
        return ''
    parentframe = stack[start][0]

    name = []
    module = inspect.getmodule(parentframe)
    # print ('module', module)
    # `modname` can be None when frame is executed directly in console
    # TODO(techtonik): consider using __main__
    if module:
        name.append(module.__name__)
        # print (module.__name__)
    # detect classname
    if 'self' in parentframe.f_locals:
        # I don't know any way to detect call from the object method
        # XXX: there seems to be no way to detect static method call - it will
        #      be just a function call
        name.append(parentframe.f_locals['self'].__class__.__name__)
    codename = parentframe.f_code.co_name
    if codename != '<module>':  # top level usually
        name.append(codename)  # function or a method
    del parentframe
    return ".".join(name)


def hide_sensitive_field(model, field_name, toggle_function, hide_function):

    moduler_headers = get_gaia_packages()

    def _hacked_method_to_model(self, name):
        # print (caller_name())
        if name == field_name:
            cn = caller_name()
            if not any(map(lambda x: cn.startswith(x), moduler_headers)):
                return super(model, self).__getattribute__(name)
            m = super(model, self).__getattribute__(name)
            if toggle_function(m):
                m = hide_function(m)
            return m
        else:
            return super(model, self).__getattribute__(name)

    def _get_full_field_content_(self, _field_name):
        if field_name in self.__dict__:
            return self.__dict__[_field_name]
        elif field_name in self.__class__.__dict__:
            return self.__class__.__dict__[_field_name]
        else:
            raise Exception('field <{}> does not exist'.format(_field_name))

    setattr(model, '__getattribute__', _hacked_method_to_model)
    setattr(model, '_get_full_field_content_', _get_full_field_content_)


def toggle_function(m):
    return m and m.isdigit() and len(m) == 11


def hide_function(m):
    return m[:2] + '**' + m[4:10] + '*'


hide_sensitive_field(User, 'username', toggle_function, hide_function)
