#!/usr/bin/env python
#
# Copyright 2011 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.
#

"""ProtoRPC WSGI service applications.

Use functions in this module to configure ProtoRPC services for use with
WSGI applications.  For more information about WSGI, please see:

  http://wsgi.org/wsgi
  http://docs.python.org/library/wsgiref.html
"""
import six

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

import cgi
import six.moves.http_client
import logging
import re

from .. import messages
from .. import registry
from .. import remote
from .. import util
from . import util as wsgi_util

__all__ = [
  'DEFAULT_REGISTRY_PATH',
  'service_app',
]

_METHOD_PATTERN = r'(?:\.([^?]+))'
_REQUEST_PATH_PATTERN = r'^(%%s)%s$' % _METHOD_PATTERN

_HTTP_BAD_REQUEST = wsgi_util.error(six.moves.http_client.BAD_REQUEST)
_HTTP_NOT_FOUND = wsgi_util.error(six.moves.http_client.NOT_FOUND)
_HTTP_UNSUPPORTED_MEDIA_TYPE = wsgi_util.error(six.moves.http_client.UNSUPPORTED_MEDIA_TYPE)

DEFAULT_REGISTRY_PATH = '/protorpc'


@util.positional(2)
def service_mapping(service_factory, service_path=r'.*', protocols=None):
  """WSGI application that handles a single ProtoRPC service mapping.

  Args:
    service_factory: Service factory for creating instances of service request
      handlers.  Either callable that takes no parameters and returns a service
      instance or a service class whose constructor requires no parameters.
    service_path: Regular expression for matching requests against.  Requests
      that do not have matching paths will cause a 404 (Not Found) response.
    protocols: remote.Protocols instance that configures supported protocols
      on server.
  """
  service_class = getattr(service_factory, 'service_class', service_factory)
  remote_methods = service_class.all_remote_methods()
  path_matcher = re.compile(_REQUEST_PATH_PATTERN % service_path)

  def protorpc_service_app(environ, start_response):
    """Actual WSGI application function."""
    path_match = path_matcher.match(environ['PATH_INFO'])
    if not path_match:
      return _HTTP_NOT_FOUND(environ, start_response)
    service_path = path_match.group(1)
    method_name = path_match.group(2)

    content_type = environ.get('CONTENT_TYPE')
    if not content_type:
      content_type = environ.get('HTTP_CONTENT_TYPE')
    if not content_type:
      return _HTTP_BAD_REQUEST(environ, start_response)

    # TODO(rafek): Handle alternate encodings.
    content_type = cgi.parse_header(content_type)[0]

    request_method = environ['REQUEST_METHOD']
    if request_method != 'POST':
      content = ('%s.%s is a ProtoRPC method.\n\n'
                 'Service %s\n\n'
                 'More about ProtoRPC: '
                 '%s\n' %
                 (service_path,
                  method_name,
                  service_class.definition_name().encode('utf-8'),
                  util.PROTORPC_PROJECT_URL))
      error_handler = wsgi_util.error(
        six.moves.http_client.METHOD_NOT_ALLOWED,
        six.moves.http_client.responses[six.moves.http_client.METHOD_NOT_ALLOWED],
        content=content,
        content_type='text/plain; charset=utf-8')
      return error_handler(environ, start_response)

    local_protocols = protocols or remote.Protocols.get_default()
    try:
      protocol = local_protocols.lookup_by_content_type(content_type)
    except KeyError:
      return _HTTP_UNSUPPORTED_MEDIA_TYPE(environ,start_response)

    def send_rpc_error(status_code, state, message, error_name=None):
      """Helper function to send an RpcStatus message as response.

      Will create static error handler and begin response.

      Args:
        status_code: HTTP integer status code.
        state: remote.RpcState enum value to send as response.
        message: Helpful message to send in response.
        error_name: Error name if applicable.

      Returns:
        List containing encoded content response using the same content-type as
        the request.
      """
      status = remote.RpcStatus(state=state,
                                error_message=message,
                                error_name=error_name)
      encoded_status = protocol.encode_message(status)
      error_handler = wsgi_util.error(
        status_code,
        content_type=protocol.default_content_type,
        content=encoded_status)
      return error_handler(environ, start_response)

    method = remote_methods.get(method_name)
    if not method:
      return send_rpc_error(six.moves.http_client.BAD_REQUEST,
                            remote.RpcState.METHOD_NOT_FOUND_ERROR,
                            'Unrecognized RPC method: %s' % method_name)

    content_length = int(environ.get('CONTENT_LENGTH') or '0')

    remote_info = method.remote
    try:
      request = protocol.decode_message(
        remote_info.request_type, environ['wsgi.input'].read(content_length))
    except (messages.ValidationError, messages.DecodeError) as err:
      return send_rpc_error(six.moves.http_client.BAD_REQUEST,
                            remote.RpcState.REQUEST_ERROR,
                            'Error parsing ProtoRPC request '
                            '(Unable to parse request content: %s)' % err)

    instance = service_factory()

    initialize_request_state = getattr(
      instance, 'initialize_request_state', None)
    if initialize_request_state:
      # TODO(rafek): This is not currently covered by tests.
      server_port = environ.get('SERVER_PORT', None)
      if server_port:
        server_port = int(server_port)

      headers = []
      for name, value in six.iteritems(environ):
        if name.startswith('HTTP_'):
          headers.append((name[len('HTTP_'):].lower().replace('_', '-'), value))
      request_state = remote.HttpRequestState(
        remote_host=environ.get('REMOTE_HOST', None),
        remote_address=environ.get('REMOTE_ADDR', None),
        server_host=environ.get('SERVER_HOST', None),
        server_port=server_port,
        http_method=request_method,
        service_path=service_path,
        headers=headers)

      initialize_request_state(request_state)

    try:
      response = method(instance, request)
      encoded_response = protocol.encode_message(response)
    except remote.ApplicationError as err:
      return send_rpc_error(six.moves.http_client.BAD_REQUEST,
                            remote.RpcState.APPLICATION_ERROR,
                            err.message,
                            err.error_name)
    except Exception as err:
      logging.exception('Encountered unexpected error from ProtoRPC '
                        'method implementation: %s (%s)' %
                        (err.__class__.__name__, err))
      return send_rpc_error(six.moves.http_client.INTERNAL_SERVER_ERROR,
                            remote.RpcState.SERVER_ERROR,
                            'Internal Server Error')

    response_headers = [('content-type', content_type)]
    start_response('%d %s' % (six.moves.http_client.OK, six.moves.http_client.responses[six.moves.http_client.OK],),
                   response_headers)
    return [encoded_response]

  # Return WSGI application.
  return protorpc_service_app


@util.positional(1)
def service_mappings(services, registry_path=DEFAULT_REGISTRY_PATH):
  """Create multiple service mappings with optional RegistryService.

  Use this function to create single WSGI application that maps to
  multiple ProtoRPC services plus an optional RegistryService.

  Example:
    services = service.service_mappings(
        [(r'/time', TimeService),
         (r'/weather', WeatherService)
        ])

    In this example, the services WSGI application will map to two services,
    TimeService and WeatherService to the '/time' and '/weather' paths
    respectively.  In addition, it will also add a ProtoRPC RegistryService
    configured to serve information about both services at the (default) path
    '/protorpc'.

  Args:
    services: If a dictionary is provided instead of a list of tuples, the
      dictionary item pairs are used as the mappings instead.
      Otherwise, a list of tuples (service_path, service_factory):
      service_path: The path to mount service on.
      service_factory: A service class or service instance factory.
    registry_path: A string to change where the registry is mapped (the default
      location is '/protorpc').  When None, no registry is created or mounted.

  Returns:
    WSGI application that serves ProtoRPC services on their respective URLs
    plus optional RegistryService.
  """
  if isinstance(services, dict):
    services = six.iteritems(services)

  final_mapping = []
  paths = set()
  registry_map = {} if registry_path else None

  for service_path, service_factory in services:
    try:
      service_class = service_factory.service_class
    except AttributeError:
      service_class = service_factory

    if service_path not in paths:
      paths.add(service_path)
    else:
      raise remote.ServiceConfigurationError(
        'Path %r is already defined in service mapping' %
        service_path.encode('utf-8'))

    if registry_map is not None:
      registry_map[service_path] = service_class

    final_mapping.append(service_mapping(service_factory, service_path))

  if registry_map is not None:
    final_mapping.append(service_mapping(
      registry.RegistryService.new_factory(registry_map), registry_path))

  return wsgi_util.first_found(final_mapping)

