#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
from collections import namedtuple
import threading
import logging

from django.conf import settings
from gm_rpcd import all
from gm_rpcd.all import RPCDFaultException
from gm_rpcd.features.raven import get_raven_client
from gm_types.error import ERROR
from gm_types.passport import USER_INFO_DETAIL_LEVEL
from helios.rpc import RPCFaultException
from helios.rpc import create_default_invoker
from gm_logging.utils import get_exception_logging_func

_base_invoker = create_default_invoker(
    debug=settings.DEBUG
).with_config(
    dump_curl=True
)

exception_logger = logging.getLogger('exception_logger')

__local = threading.local()


def get_rpc_invoker():
    return _base_invoker


rpc_client = get_rpc_invoker()


def gen(code, **kwargs):
    if code != 0:
        raise RPCDFaultException(
            code=code,
            message=ERROR.getDesc(code),
        )

    return {
        "error": 0,
        "message": '',
        "data": kwargs,
    }


_sentry_client = get_raven_client()


# 从gm-logging中取得通用的logging_exception方法,logging_excepiton的原型如下:
# logging_exception(exception_logger, sentry_client=None, send_to_sentry=True, **kwargs)
logging_exception = get_exception_logging_func(exception_logger, _sentry_client)


User = namedtuple('User', 'id user_id person_id nick_name portrait last_name')

def _format_user(user_data):
    user_data['id'] = user_data['user_id']
    u = User(**user_data)
    __local.user = u
    return u

# TODO: threadlocal 清理
def get_current_user():
    if hasattr(__local, 'user'):
        return __local.user

    # check if session_id exist
    if not all.context.session_id:
        return

    result = all.context.passport
    if result:
        try:
            u = _format_user(result)
            return u
        except:
            logging_exception()

    try:
        result = all.context.rpc['passport/info/by_session'](detail_level=USER_INFO_DETAIL_LEVEL.BASIC).unwrap()
        u = _format_user(result)
        return u
    except RPCFaultException:
        pass

    except:
        logging_exception()

    return


def get_current_user_by_session_key(session_key):
    rpc = rpc_client.with_config(session_key=session_key)
    r = rpc['passport/info/by_session']()
    result = r.unwrap_or(None)
    if not result:
        __local.user = None
        return

    result['id'] = result['user_id']
    u = User(**result)
    __local.user = u
    return u

def get_current_user_by_rpcd_request(request):
    # try get userinfo from request.passport
    passport = request.passport
    if passport:
        try:
            u = _format_user(passport)
            return u
        except:
            logging_exception() 

    return get_current_user_by_session_key(request.session_id)


def get_humanize_datetime(d):
    """humanize datetime
    """
    now = datetime.datetime.now()

    if d.year == now.year:
        if d.month == now.month:
            if d.day == now.day:
                return u'今天'
            else:
                return u'{}天前'.format(now.day - d.day)
        else:
            return d.strftime('%m-%d')
    else:
        return d.strftime('%Y-%m-%d')


class RPCMixin(object):
    @staticmethod
    def get_rpc_invoker():
        return get_rpc_invoker()

    @classmethod
    def call_rpc(cls, api_endpoint, **kwargs):
        """call rpc.

        get rpc invoker from current ctx, this method only support call rpc sequentially.
        """
        r = cls.get_rpc_invoker()
        result = r[api_endpoint](**kwargs)
        return result.unwrap()


def assert_uint(v, default=0):
    if isinstance(v, int):
        return max(0, v)
    else:
        return default

def assert_str(v, default=''):
    if isinstance(v, (str, unicode)):
        return v
    else:
        return default