#!/usr/bin/env python
#
# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Remote service library.

This module contains classes that are useful for building remote services that
conform to a standard request and response model.  To conform to this model
a service must be like the following class:

  # Each service instance only handles a single request and is then discarded.
  # Make these objects light weight.
  class Service(object):

    # It must be possible to construct service objects without any parameters.
    # If your constructor needs extra information you should provide a
    # no-argument factory function to create service instances.
    def __init__(self):
      ...

    # Each remote method must use the 'method' decorator, passing the request
    # and response message types.  The remote method itself must take a single
    # parameter which is an instance of RequestMessage and return an instance
    # of ResponseMessage.
    @method(RequestMessage, ResponseMessage)
    def remote_method(self, request):
      # Return an instance of ResponseMessage.

    # A service object may optionally implement an 'initialize_request_state'
    # method that takes as a parameter a single instance of a RequestState.  If
    # a service does not implement this method it will not receive the request
    # state.
    def initialize_request_state(self, state):
      ...

The 'Service' class is provided as a convenient base class that provides the
above functionality.  It implements all required and optional methods for a
service.  It also has convenience methods for creating factory functions that
can pass persistent global state to a new service instance.

The 'method' decorator is used to declare which methods of a class are
meant to service RPCs.  While this decorator is not responsible for handling
actual remote method invocations, such as handling sockets, handling various
RPC protocols and checking messages for correctness, it does attach information
to methods that responsible classes can examine and ensure the correctness
of the RPC.

When the method decorator is used on a method, the wrapper method will have a
'remote' property associated with it.  The 'remote' property contains the
request_type and response_type expected by the methods implementation.

On its own, the method decorator does not provide any support for subclassing
remote methods.  In order to extend a service, one would need to redecorate
the sub-classes methods.  For example:

  class MyService(Service):

    @method(DoSomethingRequest, DoSomethingResponse)
    def do_stuff(self, request):
      ... implement do_stuff ...

  class MyBetterService(MyService):

    @method(DoSomethingRequest, DoSomethingResponse)
    def do_stuff(self, request):
      response = super(MyBetterService, self).do_stuff.remote.method(request)
      ... do stuff with response ...
      return response

A Service subclass also has a Stub class that can be used with a transport for
making RPCs.  When a stub is created, it is capable of doing both synchronous
and asynchronous RPCs if the underlying transport supports it.  To make a stub
using an HTTP transport do:

  my_service = MyService.Stub(HttpTransport('<my service URL>'))

For synchronous calls, just call the expected methods on the service stub:

  request = DoSomethingRequest()
  ...
  response = my_service.do_something(request)

Each stub instance has an async object that can be used for initiating
asynchronous RPCs if the underlying protocol transport supports it.  To
make an asynchronous call, do:

  rpc = my_service.async_.do_something(request)
  response = rpc.get_response()
"""

from __future__ import with_statement
import six

__author__ = 'rafek@google.com (Rafe Kaplan)'

import functools
import logging
import sys
import threading
from wsgiref import headers as wsgi_headers

from . import message_types
from . import messages
from . import protobuf
from . import protojson
from . import util


__all__ = [
    'ApplicationError',
    'MethodNotFoundError',
    'NetworkError',
    'RequestError',
    'RpcError',
    'ServerError',
    'ServiceConfigurationError',
    'ServiceDefinitionError',

    'HttpRequestState',
    'ProtocolConfig',
    'Protocols',
    'RequestState',
    'RpcState',
    'RpcStatus',
    'Service',
    'StubBase',
    'check_rpc_status',
    'get_remote_method_info',
    'is_error_status',
    'method',
    'remote',
]


class ServiceDefinitionError(messages.Error):
  """Raised when a service is improperly defined."""


class ServiceConfigurationError(messages.Error):
  """Raised when a service is incorrectly configured."""


# TODO: Use error_name to map to specific exception message types.
class RpcStatus(messages.Message):
  """Status of on-going or complete RPC.

  Fields:
    state: State of RPC.
    error_name: Error name set by application.  Only set when
      status is APPLICATION_ERROR.  For use by application to transmit
      specific reason for error.
    error_message: Error message associated with status.
  """

  class State(messages.Enum):
    """Enumeration of possible RPC states.

    Values:
      OK: Completed successfully.
      RUNNING: Still running, not complete.
      REQUEST_ERROR: Request was malformed or incomplete.
      SERVER_ERROR: Server experienced an unexpected error.
      NETWORK_ERROR: An error occured on the network.
      APPLICATION_ERROR: The application is indicating an error.
        When in this state, RPC should also set application_error.
    """
    OK = 0
    RUNNING = 1

    REQUEST_ERROR = 2
    SERVER_ERROR = 3
    NETWORK_ERROR = 4
    APPLICATION_ERROR = 5
    METHOD_NOT_FOUND_ERROR = 6

  state = messages.EnumField(State, 1, required=True)
  error_message = messages.StringField(2)
  error_name = messages.StringField(3)


RpcState = RpcStatus.State


class RpcError(messages.Error):
  """Base class for RPC errors.

  Each sub-class of RpcError is associated with an error value from RpcState
  and has an attribute STATE that refers to that value.
  """

  def __init__(self, message, cause=None):
    super(RpcError, self).__init__(message)
    self.cause = cause

  @classmethod
  def from_state(cls, state):
    """Get error class from RpcState.

    Args:
      state: RpcState value.  Can be enum value itself, string or int.

    Returns:
      Exception class mapped to value if state is an error.  Returns None
      if state is OK or RUNNING.
    """
    return _RPC_STATE_TO_ERROR.get(RpcState(state))


class RequestError(RpcError):
  """Raised when wrong request objects received during method invocation."""

  STATE = RpcState.REQUEST_ERROR


class MethodNotFoundError(RequestError):
  """Raised when unknown method requested by RPC."""

  STATE = RpcState.METHOD_NOT_FOUND_ERROR


class NetworkError(RpcError):
  """Raised when network error occurs during RPC."""

  STATE = RpcState.NETWORK_ERROR


class ServerError(RpcError):
  """Unexpected error occured on server."""

  STATE = RpcState.SERVER_ERROR


class ApplicationError(RpcError):
  """Raised for application specific errors.

  Attributes:
    error_name: Application specific error name for exception.
  """

  STATE = RpcState.APPLICATION_ERROR

  def __init__(self, message, error_name=None):
    """Constructor.

    Args:
      message: Application specific error message.
      error_name: Application specific error name.  Must be None, string
      or unicode string.
    """
    super(ApplicationError, self).__init__(message)
    self.error_name = error_name

  def __str__(self):
    return self.args[0] or ''

  def __repr__(self):
    if self.error_name is None:
      error_format = ''
    else:
      error_format = ', %r' % self.error_name
    return '%s(%r%s)' % (type(self).__name__, self.args[0], error_format)


_RPC_STATE_TO_ERROR = {
  RpcState.REQUEST_ERROR: RequestError,
  RpcState.NETWORK_ERROR: NetworkError,
  RpcState.SERVER_ERROR: ServerError,
  RpcState.APPLICATION_ERROR: ApplicationError,
  RpcState.METHOD_NOT_FOUND_ERROR: MethodNotFoundError,
}

class _RemoteMethodInfo(object):
  """Object for encapsulating remote method information.

  An instance of this method is associated with the 'remote' attribute
  of the methods 'invoke_remote_method' instance.

  Instances of this class are created by the remote decorator and should not
  be created directly.
  """

  def __init__(self,
               method,
               request_type,
               response_type):
    """Constructor.

    Args:
      method: The method which implements the remote method.  This is a
        function that will act as an instance method of a class definition
        that is decorated by '@method'.  It must always take 'self' as its
        first parameter.
      request_type: Expected request type for the remote method.
      response_type: Expected response type for the remote method.
    """
    self.__method = method
    self.__request_type = request_type
    self.__response_type = response_type

  @property
  def method(self):
    """Original undecorated method."""
    return self.__method

  @property
  def request_type(self):
    """Expected request type for remote method."""
    if isinstance(self.__request_type, six.string_types):
      self.__request_type = messages.find_definition(
        self.__request_type,
        relative_to=sys.modules[self.__method.__module__])
    return self.__request_type

  @property
  def response_type(self):
    """Expected response type for remote method."""
    if isinstance(self.__response_type, six.string_types):
      self.__response_type = messages.find_definition(
        self.__response_type,
        relative_to=sys.modules[self.__method.__module__])
    return self.__response_type


def method(request_type=message_types.VoidMessage,
           response_type=message_types.VoidMessage):
  """Method decorator for creating remote methods.

  Args:
    request_type: Message type of expected request.
    response_type: Message type of expected response.

  Returns:
    'remote_method_wrapper' function.

  Raises:
    TypeError: if the request_type or response_type parameters are not
      proper subclasses of messages.Message.
  """
  if (not isinstance(request_type, six.string_types) and
      (not isinstance(request_type, type) or
       not issubclass(request_type, messages.Message) or
       request_type is messages.Message)):
    raise TypeError(
        'Must provide message class for request-type.  Found %s',
        request_type)

  if (not isinstance(response_type, six.string_types) and
      (not isinstance(response_type, type) or
       not issubclass(response_type, messages.Message) or
       response_type is messages.Message)):
    raise TypeError(
        'Must provide message class for response-type.  Found %s',
        response_type)

  def remote_method_wrapper(method):
    """Decorator used to wrap method.

    Args:
      method: Original method being wrapped.

    Returns:
      'invoke_remote_method' function responsible for actual invocation.
      This invocation function instance is assigned an attribute 'remote'
      which contains information about the remote method:
        request_type: Expected request type for remote method.
        response_type: Response type returned from remote method.

    Raises:
      TypeError: If request_type or response_type is not a subclass of Message
        or is the Message class itself.
    """

    @functools.wraps(method)
    def invoke_remote_method(service_instance, request):
      """Function used to replace original method.

      Invoke wrapped remote method.  Checks to ensure that request and
      response objects are the correct types.

      Does not check whether messages are initialized.

      Args:
        service_instance: The service object whose method is being invoked.
          This is passed to 'self' during the invocation of the original
          method.
        request: Request message.

      Returns:
        Results of calling wrapped remote method.

      Raises:
        RequestError: Request object is not of the correct type.
        ServerError: Response object is not of the correct type.
      """
      if not isinstance(request, remote_method_info.request_type):
        raise RequestError('Method %s.%s expected request type %s, '
                           'received %s' %
                           (type(service_instance).__name__,
                            method.__name__,
                            remote_method_info.request_type,
                            type(request)))
      response = method(service_instance, request)
      if not isinstance(response, remote_method_info.response_type):
        raise ServerError('Method %s.%s expected response type %s, '
                          'sent %s' %
                          (type(service_instance).__name__,
                           method.__name__,
                           remote_method_info.response_type,
                           type(response)))
      return response

    remote_method_info = _RemoteMethodInfo(method,
                                           request_type,
                                           response_type)

    invoke_remote_method.remote = remote_method_info
    return invoke_remote_method

  return remote_method_wrapper


def remote(request_type, response_type):
  """Temporary backward compatibility alias for method."""
  logging.warning('The remote decorator has been renamed method.  It will be '
                  'removed in very soon from future versions of ProtoRPC.')
  return method(request_type, response_type)


def get_remote_method_info(method):
  """Get remote method info object from remote method.

  Returns:
    Remote method info object if method is a remote method, else None.
  """
  if not callable(method):
    return None

  try:
    method_info = method.remote
  except AttributeError:
    return None

  if not isinstance(method_info, _RemoteMethodInfo):
    return None

  return method_info


class StubBase(object):
  """Base class for client side service stubs.

  The remote method stubs are created by the _ServiceClass meta-class
  when a Service class is first created.  The resulting stub will
  extend both this class and the service class it handles communications for.

  Assume that there is a service:

    class NewContactRequest(messages.Message):

      name = messages.StringField(1, required=True)
      phone = messages.StringField(2)
      email = messages.StringField(3)

    class NewContactResponse(message.Message):

      contact_id = messages.StringField(1)

    class AccountService(remote.Service):

      @remote.method(NewContactRequest, NewContactResponse):
      def new_contact(self, request):
        ... implementation ...

  A stub of this service can be called in two ways.  The first is to pass in a
  correctly initialized NewContactRequest message:

    request = NewContactRequest()
    request.name = 'Bob Somebody'
    request.phone = '+1 415 555 1234'

    response = account_service_stub.new_contact(request)

  The second way is to pass in keyword parameters that correspond with the root
  request message type:

      account_service_stub.new_contact(name='Bob Somebody',
                                       phone='+1 415 555 1234')

  The second form will create a request message of the appropriate type.
  """

  def __init__(self, transport):
    """Constructor.

    Args:
      transport: Underlying transport to communicate with remote service.
    """
    self.__transport = transport

  @property
  def transport(self):
    """Transport used to communicate with remote service."""
    return self.__transport


class _ServiceClass(type):
  """Meta-class for service class."""

  def __new_async_method(cls, remote):
    """Create asynchronous method for Async handler.

    Args:
      remote: RemoteInfo to create method for.
    """
    def async_method(self, *args, **kwargs):
      """Asynchronous remote method.

      Args:
        self: Instance of StubBase.Async subclass.

        Stub methods either take a single positional argument when a full
        request message is passed in, or keyword arguments, but not both.

        See docstring for StubBase for more information on how to use remote
        stub methods.

      Returns:
        Rpc instance used to represent asynchronous RPC.
      """
      if args and kwargs:
        raise TypeError('May not provide both args and kwargs')

      if not args:
        # Construct request object from arguments.
        request = remote.request_type()
        for name, value in six.iteritems(kwargs):
          setattr(request, name, value)
      else:
        # First argument is request object.
        request = args[0]

      return self.transport.send_rpc(remote, request)

    async_method.__name__ = remote.method.__name__
    async_method = util.positional(2)(async_method)
    async_method.remote = remote
    return async_method

  def __new_sync_method(cls, async_method):
    """Create synchronous method for stub.

    Args:
      async_method: asynchronous method to delegate calls to.
    """
    def sync_method(self, *args, **kwargs):
      """Synchronous remote method.

      Args:
        self: Instance of StubBase.Async subclass.
        args: Tuple (request,):
          request: Request object.
        kwargs: Field values for request.  Must be empty if request object
          is provided.

      Returns:
        Response message from synchronized RPC.
      """
      return async_method(self.async_, *args, **kwargs).response
    sync_method.__name__ = async_method.__name__
    sync_method.remote = async_method.remote
    return sync_method

  def __create_async_methods(cls, remote_methods):
    """Construct a dictionary of asynchronous methods based on remote methods.

    Args:
      remote_methods: Dictionary of methods with associated RemoteInfo objects.

    Returns:
      Dictionary of asynchronous methods with assocaited RemoteInfo objects.
      Results added to AsyncStub subclass.
    """
    async_methods = {}
    for method_name, method in remote_methods.items():
      async_methods[method_name] = cls.__new_async_method(method.remote)
    return async_methods

  def __create_sync_methods(cls, async_methods):
    """Construct a dictionary of synchronous methods based on remote methods.

    Args:
      async_methods: Dictionary of async methods to delegate calls to.

    Returns:
      Dictionary of synchronous methods with assocaited RemoteInfo objects.
      Results added to Stub subclass.
    """
    sync_methods = {}
    for method_name, async_method in async_methods.items():
      sync_methods[method_name] = cls.__new_sync_method(async_method)
    return sync_methods

  def __new__(cls, name, bases, dct):
    """Instantiate new service class instance."""
    if StubBase not in bases:
      # Collect existing remote methods.
      base_methods = {}
      for base in bases:
        try:
          remote_methods = base.__remote_methods
        except AttributeError:
          pass
        else:
          base_methods.update(remote_methods)

      # Set this class private attribute so that base_methods do not have
      # to be recacluated in __init__.
      dct['_ServiceClass__base_methods'] = base_methods

      for attribute, value in dct.items():
        base_method = base_methods.get(attribute, None)
        if base_method:
          if not callable(value):
            raise ServiceDefinitionError(
              'Must override %s in %s with a method.' % (
                attribute, name))

          if get_remote_method_info(value):
            raise ServiceDefinitionError(
              'Do not use method decorator when overloading remote method %s '
              'on service %s.' %
              (attribute, name))

          base_remote_method_info = get_remote_method_info(base_method)
          remote_decorator = method(
            base_remote_method_info.request_type,
            base_remote_method_info.response_type)
          new_remote_method = remote_decorator(value)
          dct[attribute] = new_remote_method

    return type.__new__(cls, name, bases, dct)

  def __init__(cls, name, bases, dct):
    """Create uninitialized state on new class."""
    type.__init__(cls, name, bases, dct)

    # Only service implementation classes should have remote methods and stub
    # sub classes created.  Stub implementations have their own methods passed
    # in to the type constructor.
    if StubBase not in bases:
      # Create list of remote methods.
      cls.__remote_methods = dict(cls.__base_methods)

      for attribute, value in dct.items():
        value = getattr(cls, attribute)
        remote_method_info = get_remote_method_info(value)
        if remote_method_info:
          cls.__remote_methods[attribute] = value

      # Build asynchronous stub class.
      stub_attributes = {'Service': cls}
      async_methods = cls.__create_async_methods(cls.__remote_methods)
      stub_attributes.update(async_methods)
      async_class = type('AsyncStub', (StubBase, cls), stub_attributes)
      cls.AsyncStub = async_class

      # Constructor for synchronous stub class.
      def __init__(self, transport):
        """Constructor.

        Args:
          transport: Underlying transport to communicate with remote service.
        """
        super(cls.Stub, self).__init__(transport)
        self.async_ = cls.AsyncStub(transport)

      # Build synchronous stub class.
      stub_attributes = {'Service': cls,
                         '__init__': __init__}
      stub_attributes.update(cls.__create_sync_methods(async_methods))

      cls.Stub = type('Stub', (StubBase, cls), stub_attributes)

  @staticmethod
  def all_remote_methods(cls):
    """Get all remote methods of service.

    Returns:
      Dict from method name to unbound method.
    """
    return dict(cls.__remote_methods)


class RequestState(object):
  """Request state information.

  Properties:
    remote_host: Remote host name where request originated.
    remote_address: IP address where request originated.
    server_host: Host of server within which service resides.
    server_port: Post which service has recevied request from.
  """

  @util.positional(1)
  def __init__(self,
               remote_host=None,
               remote_address=None,
               server_host=None,
               server_port=None):
    """Constructor.

    Args:
      remote_host: Assigned to property.
      remote_address: Assigned to property.
      server_host: Assigned to property.
      server_port: Assigned to property.
    """
    self.__remote_host = remote_host
    self.__remote_address = remote_address
    self.__server_host = server_host
    self.__server_port = server_port

  @property
  def remote_host(self):
    return self.__remote_host

  @property
  def remote_address(self):
    return self.__remote_address

  @property
  def server_host(self):
    return self.__server_host

  @property
  def server_port(self):
    return self.__server_port

  def _repr_items(self):
    for name in ['remote_host',
                 'remote_address',
                 'server_host',
                 'server_port']:
      yield name, getattr(self, name)

  def __repr__(self):
    """String representation of state."""
    state = [self.__class__.__name__]
    for name, value in self._repr_items():
      if value:
        state.append('%s=%r' % (name, value))

    return '<%s>' % (' '.join(state),)


class HttpRequestState(RequestState):
  """HTTP request state information.

  NOTE: Does not attempt to represent certain types of information from the
  request such as the query string as query strings are not permitted in
  ProtoRPC URLs unless required by the underlying message format.

  Properties:
    headers: wsgiref.headers.Headers instance of HTTP request headers.
    http_method: HTTP method as a string.
    service_path: Path on HTTP service where service is mounted.  This path
      will not include the remote method name.
  """

  @util.positional(1)
  def __init__(self,
               http_method=None,
               service_path=None,
               headers=None,
               **kwargs):
    """Constructor.

    Args:
      Same as RequestState, including:
        http_method: Assigned to property.
        service_path: Assigned to property.
        headers: HTTP request headers.  If instance of Headers, assigned to
          property without copying.  If dict, will convert to name value pairs
          for use with Headers constructor.  Otherwise, passed as parameters to
          Headers constructor.
    """
    super(HttpRequestState, self).__init__(**kwargs)

    self.__http_method = http_method
    self.__service_path = service_path

    # Initialize headers.
    if isinstance(headers, dict):
      header_list = []
      for key, value in sorted(headers.items()):
        if not isinstance(value, list):
          value = [value]
        for item in value:
          header_list.append((key, item))
        headers = header_list
    self.__headers = wsgi_headers.Headers(headers or [])

  @property
  def http_method(self):
    return self.__http_method

  @property
  def service_path(self):
    return self.__service_path

  @property
  def headers(self):
    return self.__headers

  def _repr_items(self):
    for item in super(HttpRequestState, self)._repr_items():
      yield item

    for name in ['http_method', 'service_path']:
      yield name, getattr(self, name)

    yield 'headers', list(self.headers.items())


class Service(six.with_metaclass(_ServiceClass, object)):
  """Service base class.

  Base class used for defining remote services.  Contains reflection functions,
  useful helpers and built-in remote methods.

  Services are expected to be constructed via either a constructor or factory
  which takes no parameters.  However, it might be required that some state or
  configuration is passed in to a service across multiple requests.

  To do this, define parameters to the constructor of the service and use
  the 'new_factory' class method to build a constructor that will transmit
  parameters to the constructor.  For example:

    class MyService(Service):

      def __init__(self, configuration, state):
        self.configuration = configuration
        self.state = state

    configuration = MyServiceConfiguration()
    global_state = MyServiceState()

    my_service_factory = MyService.new_factory(configuration,
                                               state=global_state)

  The contract with any service handler is that a new service object is created
  to handle each user request, and that the construction does not take any
  parameters.  The factory satisfies this condition:

    new_instance = my_service_factory()
    assert new_instance.state is global_state

  Attributes:
    request_state: RequestState set via initialize_request_state.
  """

  __request_state = None

  @classmethod
  def all_remote_methods(cls):
    """Get all remote methods for service class.

    Built-in methods do not appear in the dictionary of remote methods.

    Returns:
      Dictionary mapping method name to remote method.
    """
    return _ServiceClass.all_remote_methods(cls)

  @classmethod
  def new_factory(cls, *args, **kwargs):
    """Create factory for service.

    Useful for passing configuration or state objects to the service.  Accepts
    arbitrary parameters and keywords, however, underlying service must accept
    also accept not other parameters in its constructor.

    Args:
      args: Args to pass to service constructor.
      kwargs: Keyword arguments to pass to service constructor.

    Returns:
      Factory function that will create a new instance and forward args and
      keywords to the constructor.
    """

    def service_factory():
      return cls(*args, **kwargs)

    # Update docstring so that it is easier to debug.
    full_class_name = '%s.%s' % (cls.__module__, cls.__name__)
    service_factory.__doc__ = (
        'Creates new instances of service %s.\n\n'
        'Returns:\n'
        '  New instance of %s.'
        % (cls.__name__, full_class_name))

    # Update name so that it is easier to debug the factory function.
    service_factory.__name__ = '%s_service_factory' % cls.__name__

    service_factory.service_class = cls

    return service_factory

  def initialize_request_state(self, request_state):
    """Save request state for use in remote method.

    Args:
      request_state: RequestState instance.
    """
    self.__request_state = request_state

  @classmethod
  def definition_name(cls):
    """Get definition name for Service class.

    Package name is determined by the global 'package' attribute in the
    module that contains the Service definition.  If no 'package' attribute
    is available, uses module name.  If no module is found, just uses class
    name as name.

    Returns:
      Fully qualified service name.
    """
    try:
      return cls.__definition_name
    except AttributeError:
      outer_definition_name = cls.outer_definition_name()
      if outer_definition_name is None:
        cls.__definition_name = cls.__name__
      else:
        cls.__definition_name = '%s.%s' % (outer_definition_name, cls.__name__)

      return cls.__definition_name

  @classmethod
  def outer_definition_name(cls):
    """Get outer definition name.

    Returns:
      Package for service.  Services are never nested inside other definitions.
    """
    return cls.definition_package()

  @classmethod
  def definition_package(cls):
    """Get package for service.

    Returns:
      Package name for service.
    """
    try:
      return cls.__definition_package
    except AttributeError:
      cls.__definition_package = util.get_package_for_module(cls.__module__)

    return cls.__definition_package

  @property
  def request_state(self):
    """Request state associated with this Service instance."""
    return self.__request_state


def is_error_status(status):
  """Function that determines whether the RPC status is an error.

  Args:
    status: Initialized RpcStatus message to check for errors.
  """
  status.check_initialized()
  return RpcError.from_state(status.state) is not None


def check_rpc_status(status):
  """Function converts an error status to a raised exception.

  Args:
    status: Initialized RpcStatus message to check for errors.

  Raises:
    RpcError according to state set on status, if it is an error state.
  """
  status.check_initialized()
  error_class = RpcError.from_state(status.state)
  if error_class is not None:
    if error_class is ApplicationError:
      raise error_class(status.error_message, status.error_name)
    else:
      raise error_class(status.error_message)


class ProtocolConfig(object):
  """Configuration for single protocol mapping.

  A read-only protocol configuration provides a given protocol implementation
  with a name and a set of content-types that it recognizes.

  Properties:
    protocol: The protocol implementation for configuration (usually a module,
      for example, protojson, protobuf, etc.).  This is an object that has the
      following attributes:
        CONTENT_TYPE: Used as the default content-type if default_content_type
          is not set.
        ALTERNATIVE_CONTENT_TYPES (optional): A list of alternative
          content-types to the default that indicate the same protocol.
        encode_message: Function that matches the signature of
          ProtocolConfig.encode_message.  Used for encoding a ProtoRPC message.
        decode_message: Function that matches the signature of
          ProtocolConfig.decode_message.  Used for decoding a ProtoRPC message.
    name: Name of protocol configuration.
    default_content_type: The default content type for the protocol.  Overrides
      CONTENT_TYPE defined on protocol.
    alternative_content_types: A list of alternative content-types supported
      by the protocol.  Must not contain the default content-type, nor
      duplicates.  Overrides ALTERNATIVE_CONTENT_TYPE defined on protocol.
    content_types: A list of all content-types supported by configuration.
      Combination of default content-type and alternatives.
  """

  def __init__(self,
               protocol,
               name,
               default_content_type=None,
               alternative_content_types=None):
    """Constructor.

    Args:
      protocol: The protocol implementation for configuration.
      name: The name of the protocol configuration.
      default_content_type: The default content-type for protocol.  If none
        provided it will check protocol.CONTENT_TYPE.
      alternative_content_types:  A list of content-types.  If none provided,
        it will check protocol.ALTERNATIVE_CONTENT_TYPES.  If that attribute
        does not exist, will be an empty tuple.

    Raises:
      ServiceConfigurationError if there are any duplicate content-types.
    """
    self.__protocol = protocol
    self.__name = name
    self.__default_content_type = (default_content_type or
                                   protocol.CONTENT_TYPE).lower()
    if alternative_content_types is None:
      alternative_content_types = getattr(protocol,
                                          'ALTERNATIVE_CONTENT_TYPES',
                                          ())
    self.__alternative_content_types = tuple(
      content_type.lower() for content_type in alternative_content_types)
    self.__content_types = (
      (self.__default_content_type,) + self.__alternative_content_types)

    # Detect duplicate content types in definition.
    previous_type = None
    for content_type in sorted(self.content_types):
      if content_type == previous_type:
        raise ServiceConfigurationError(
          'Duplicate content-type %s' % content_type)
      previous_type = content_type

  @property
  def protocol(self):
    return self.__protocol

  @property
  def name(self):
    return self.__name

  @property
  def default_content_type(self):
    return self.__default_content_type

  @property
  def alternate_content_types(self):
    return self.__alternative_content_types

  @property
  def content_types(self):
    return self.__content_types

  def encode_message(self, message):
    """Encode message.

    Args:
      message: Message instance to encode.

    Returns:
      String encoding of Message instance encoded in protocol's format.
    """
    return self.__protocol.encode_message(message)

  def decode_message(self, message_type, encoded_message):
    """Decode buffer to Message instance.

    Args:
      message_type: Message type to decode data to.
      encoded_message: Encoded version of message as string.

    Returns:
      Decoded instance of message_type.
    """
    return self.__protocol.decode_message(message_type, encoded_message)


class Protocols(object):
  """Collection of protocol configurations.

  Used to describe a complete set of content-type mappings for multiple
  protocol configurations.

  Properties:
    names: Sorted list of the names of registered protocols.
    content_types: Sorted list of supported content-types.
  """

  __default_protocols = None
  __lock = threading.Lock()

  def __init__(self):
    """Constructor."""
    self.__by_name = {}
    self.__by_content_type = {}

  def add_protocol_config(self, config):
    """Add a protocol configuration to protocol mapping.

    Args:
      config: A ProtocolConfig.

    Raises:
      ServiceConfigurationError if protocol.name is already registered
        or any of it's content-types are already registered.
    """
    if config.name in self.__by_name:
      raise ServiceConfigurationError(
        'Protocol name %r is already in use' % config.name)
    for content_type in config.content_types:
      if content_type in self.__by_content_type:
        raise ServiceConfigurationError(
          'Content type %r is already in use' % content_type)

    self.__by_name[config.name] = config
    self.__by_content_type.update((t, config) for t in config.content_types)

  def add_protocol(self, *args, **kwargs):
    """Add a protocol configuration from basic parameters.

    Simple helper method that creates and registeres a ProtocolConfig instance.
    """
    self.add_protocol_config(ProtocolConfig(*args, **kwargs))

  @property
  def names(self):
    return tuple(sorted(self.__by_name))

  @property
  def content_types(self):
    return tuple(sorted(self.__by_content_type))

  def lookup_by_name(self, name):
    """Look up a ProtocolConfig by name.

    Args:
      name: Name of protocol to look for.

    Returns:
      ProtocolConfig associated with name.

    Raises:
      KeyError if there is no protocol for name.
    """
    return self.__by_name[name.lower()]

  def lookup_by_content_type(self, content_type):
    """Look up a ProtocolConfig by content-type.

    Args:
      content_type: Content-type to find protocol configuration for.

    Returns:
      ProtocolConfig associated with content-type.

    Raises:
      KeyError if there is no protocol for content-type.
    """
    return self.__by_content_type[content_type.lower()]

  @classmethod
  def new_default(cls):
    """Create default protocols configuration.

    Returns:
      New Protocols instance configured for protobuf and protorpc.
    """
    protocols = cls()
    protocols.add_protocol(protobuf, 'protobuf')
    protocols.add_protocol(protojson.ProtoJson.get_default(), 'protojson')
    return protocols

  @classmethod
  def get_default(cls):
    """Get the global default Protocols instance.

    Returns:
      Current global default Protocols instance.
    """
    default_protocols = cls.__default_protocols
    if default_protocols is None:
      with cls.__lock:
        default_protocols = cls.__default_protocols
        if default_protocols is None:
          default_protocols = cls.new_default()
          cls.__default_protocols = default_protocols
    return default_protocols

  @classmethod
  def set_default(cls, protocols):
    """Set the global default Protocols instance.

    Args:
      protocols: A Protocols instance.

    Raises:
      TypeError: If protocols is not an instance of Protocols.
    """
    if not isinstance(protocols, Protocols):
      raise TypeError(
        'Expected value of type "Protocols", found %r' % protocols)
    with cls.__lock:
      cls.__default_protocols = protocols
