# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import six
import logging
import funcsigs

from nanny_rpc_client import RetryingRpcClient

from saas.library.python.singleton import Singleton
from saas.library.python.token_store import PersistentTokenStore


class SingletonWithLogging(Singleton, type):
    def __new__(mcs, name, bases, dct):
        logging_cls = super(SingletonWithLogging, mcs).__new__(mcs, name, bases, dct)
        logging_cls.LOGGER = logging.getLogger(name)
        return logging_cls


class NannyRpcClientBase(six.with_metaclass(SingletonWithLogging)):
    LOGGER = logging.getLogger(__name__)

    # Override in child class
    _OAUTH_SLUG = 'nanny'
    _CLIENT_CLASS = RetryingRpcClient
    _RPC_URL = None
    _API_STUB = None
    _identity = list()  # __init__ arguments that uniquely identify instance identity

    # Configured client will be available here
    _CLIENT = None

    @classmethod
    def _get_instance_id(cls, args, kwargs):
        signature = funcsigs.signature(cls.__init__)
        bound_params = signature.bind(cls, *args, **kwargs)
        identity = [cls, ]
        for i in cls._identity:
            identity.append(bound_params.arguments[i])
        return tuple(identity)

    @classmethod
    def _extra_actions(cls, instance, args, kwargs):
        pass
        # signature = funcsigs.signature(cls.__init__)
        # bound_params = signature.bind(cls, *args, **kwargs)
        # if 'proto_msg' in bound_params.arguments and bound_params.arguments['proto_msg'] is not None:
        #     instance._porto_msg = bound_params.arguments['proto_msg']

    @classmethod
    def _init_client(cls):
        if cls._CLIENT is not None:
            cls.LOGGER.debug('%s client already configured')
        else:
            oauth_token = PersistentTokenStore.get_token_from_store_env_or_file(cls._OAUTH_SLUG)
            if cls._RPC_URL is None or cls._API_STUB is None:
                raise RuntimeError('{c}._RPC_URL or {c}._API_STUB not set'.format(c=cls.__name__))
            client = cls._CLIENT_CLASS(rpc_url=cls._RPC_URL, oauth_token=oauth_token, retry_connection_errors=True, request_timeout=30)
            cls._CLIENT = cls._API_STUB(client)

    def __init__(self):
        self._init_client()
