# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""A library supporting use of the Google API Server.

This library helps you configure a set of ProtoRPC services to act as
Endpoints backends.  In addition to translating ProtoRPC to Endpoints
compatible errors, it exposes a helper service that describes your services.

  Usage:
  1) Create an endpoints.api_server instead of a webapp.WSGIApplication.
  2) Annotate your ProtoRPC Service class with @endpoints.api to give your
     API a name, version, and short description
  3) To return an error from Google API Server raise an endpoints.*Exception
     The ServiceException classes specify the http status code returned.

     For example:
     raise endpoints.UnauthorizedException("Please log in as an admin user")


  Sample usage:
  - - - - app.yaml - - - -

  handlers:
  # Path to your API backend.
  # /_ah/api/.* is the default. Using the base_path parameter, you can
  # customize this to whichever base path you desire.
  - url: /_ah/api/.*
    # For the legacy python runtime this would be "script: services.py"
    script: services.app

  - - - - services.py - - - -

  import endpoints
  import postservice

  app = endpoints.api_server([postservice.PostService], debug=True)

  - - - - postservice.py - - - -

  @endpoints.api(name='guestbook', version='v0.2', description='Guestbook API')
  class PostService(remote.Service):
    ...
    @endpoints.method(GetNotesRequest, Notes, name='notes.list', path='notes',
                       http_method='GET')
    def list(self, request):
      raise endpoints.UnauthorizedException("Please log in as an admin user")
"""

from __future__ import absolute_import

import cgi
from six.moves import http_client
import json
import logging
import os

from google.appengine.api import app_identity

from . import api_config
from . import api_exceptions
from . import endpoints_dispatcher
from . import message_types
from . import messages
from . import protojson
from . import remote
from . import util

_logger = logging.getLogger(__name__)
package = 'google.appengine.endpoints'


__all__ = [
    'ApiConfigRegistry',
    'api_server',
    'EndpointsErrorMessage',
    'package',
]


class _Remapped405Exception(api_exceptions.ServiceException):
  """Method Not Allowed (405) ends up being remapped to 501.

  This is included here for compatibility with the Java implementation.  The
  Google Cloud Endpoints server remaps HTTP 405 to 501.
  """
  http_status = http_client.METHOD_NOT_ALLOWED


class _Remapped408Exception(api_exceptions.ServiceException):
  """Request Timeout (408) ends up being remapped to 503.

  This is included here for compatibility with the Java implementation.  The
  Google Cloud Endpoints server remaps HTTP 408 to 503.
  """
  http_status = http_client.REQUEST_TIMEOUT


_ERROR_NAME_MAP = dict((http_client.responses[c.http_status], c) for c in [
    api_exceptions.BadRequestException,
    api_exceptions.UnauthorizedException,
    api_exceptions.ForbiddenException,
    api_exceptions.NotFoundException,
    _Remapped405Exception,
    _Remapped408Exception,
    api_exceptions.ConflictException,
    api_exceptions.GoneException,
    api_exceptions.PreconditionFailedException,
    api_exceptions.RequestEntityTooLargeException,
    api_exceptions.InternalServerErrorException
    ])

_ALL_JSON_CONTENT_TYPES = frozenset(
    [protojson.EndpointsProtoJson.CONTENT_TYPE] +
    protojson.EndpointsProtoJson.ALTERNATIVE_CONTENT_TYPES)


# Message format for returning error back to Google Endpoints frontend.
class EndpointsErrorMessage(messages.Message):
  """Message for returning error back to Google Endpoints frontend.

  Fields:
    state: State of RPC, should be 'APPLICATION_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)


# pylint: disable=g-bad-name
def _get_app_revision(environ=None):
  """Gets the app revision (minor app version) of the current app.

  Args:
    environ: A dictionary with a key CURRENT_VERSION_ID that maps to a version
      string of the format <major>.<minor>.

  Returns:
    The app revision (minor version) of the current app, or None if one couldn't
    be found.
  """
  if environ is None:
    environ = os.environ
  if 'CURRENT_VERSION_ID' in environ:
    return environ['CURRENT_VERSION_ID'].split('.')[1]


class ApiConfigRegistry(object):
  """Registry of active APIs"""

  def __init__(self):
    # Set of API classes that have been registered.
    self.__registered_classes = set()
    # Set of API config contents served by this App Engine AppId/version
    self.__api_configs = []
    # Map of API method name to ProtoRPC method name.
    self.__api_methods = {}

  # pylint: disable=g-bad-name
  def register_backend(self, config_contents):
    """Register a single API and its config contents.

    Args:
      config_contents: Dict containing API configuration.
    """
    if config_contents is None:
      return
    self.__register_class(config_contents)
    self.__api_configs.append(config_contents)
    self.__register_methods(config_contents)

  def __register_class(self, parsed_config):
    """Register the class implementing this config, so we only add it once.

    Args:
      parsed_config: The JSON object with the API configuration being added.

    Raises:
      ApiConfigurationError: If the class has already been registered.
    """
    methods = parsed_config.get('methods')
    if not methods:
      return

    # Determine the name of the class that implements this configuration.
    service_classes = set()
    for method in methods.values():
      rosy_method = method.get('rosyMethod')
      if rosy_method and '.' in rosy_method:
        method_class = rosy_method.split('.', 1)[0]
        service_classes.add(method_class)

    for service_class in service_classes:
      if service_class in self.__registered_classes:
        raise api_exceptions.ApiConfigurationError(
            'API class %s has already been registered.' % service_class)
      self.__registered_classes.add(service_class)

  def __register_methods(self, parsed_config):
    """Register all methods from the given api config file.

    Methods are stored in a map from method_name to rosyMethod,
    the name of the ProtoRPC method to be called on the backend.
    If no rosyMethod was specified the value will be None.

    Args:
      parsed_config: The JSON object with the API configuration being added.
    """
    methods = parsed_config.get('methods')
    if not methods:
      return

    for method_name, method in methods.items():
      self.__api_methods[method_name] = method.get('rosyMethod')

  def lookup_api_method(self, api_method_name):
    """Looks an API method up by name to find the backend method to call.

    Args:
      api_method_name: Name of the method in the API that was called.

    Returns:
      Name of the ProtoRPC method called on the backend, or None if not found.
    """
    return self.__api_methods.get(api_method_name)

  def all_api_configs(self):
    """Return a list of all API configration specs as registered above."""
    return self.__api_configs


class _ApiServer(object):
  """ProtoRPC wrapper, registers APIs and formats errors for Google API Server.

  - - - - ProtoRPC error format - - - -
  HTTP/1.0 400 Please log in as an admin user.
  content-type: application/json

  {
    "state": "APPLICATION_ERROR",
    "error_message": "Please log in as an admin user",
    "error_name": "unauthorized",
  }

  - - - - Reformatted error format - - - -
  HTTP/1.0 401 UNAUTHORIZED
  content-type: application/json

  {
    "state": "APPLICATION_ERROR",
    "error_message": "Please log in as an admin user"
  }
  """
  # Silence lint warning about invalid const name
  # pylint: disable=g-bad-name
  __SERVER_SOFTWARE = 'SERVER_SOFTWARE'
  __HEADER_NAME_PEER = 'HTTP_X_APPENGINE_PEER'
  __GOOGLE_PEER = 'apiserving'
  # A common EndpointsProtoJson for all _ApiServer instances.  At the moment,
  # EndpointsProtoJson looks to be thread safe.
  __PROTOJSON = protojson.EndpointsProtoJson()

  def __init__(self, api_services, **kwargs):
    """Initialize an _ApiServer instance.

    The primary function of this method is to set up the WSGIApplication
    instance for the service handlers described by the services passed in.
    Additionally, it registers each API in ApiConfigRegistry for later use
    in the BackendService.getApiConfigs() (API config enumeration service).

    Args:
      api_services: List of protorpc.remote.Service classes implementing the API
        or a list of _ApiDecorator instances that decorate the service classes
        for an API.
      **kwargs: Passed through to protorpc.wsgi.service.service_handlers except:
        protocols - ProtoRPC protocols are not supported, and are disallowed.

    Raises:
      TypeError: if protocols are configured (this feature is not supported).
      ApiConfigurationError: if there's a problem with the API config.
    """
    self.base_paths = set()

    for entry in api_services[:]:
      # pylint: disable=protected-access
      if isinstance(entry, api_config._ApiDecorator):
        api_services.remove(entry)
        api_services.extend(entry.get_api_classes())

    # Record the API services for quick discovery doc generation
    self.api_services = api_services

    # Record the base paths
    for entry in api_services:
      self.base_paths.add(entry.api_info.base_path)

    self.api_config_registry = ApiConfigRegistry()
    self.api_name_version_map = self.__create_name_version_map(api_services)
    protorpc_services = self.__register_services(self.api_name_version_map,
                                                 self.api_config_registry)

    # Disallow protocol configuration for now, Lily is json-only.
    if 'protocols' in kwargs:
      raise TypeError('__init__() got an unexpected keyword argument '
                      "'protocols'")
    protocols = remote.Protocols()
    protocols.add_protocol(self.__PROTOJSON, 'protojson')
    remote.Protocols.set_default(protocols)

    # This variable is not used in Endpoints 1.1, but let's pop it out here
    # so it doesn't result in an unexpected keyword argument downstream.
    kwargs.pop('restricted', None)

    from protorpc.wsgi import service as wsgi_service
    self.service_app = wsgi_service.service_mappings(protorpc_services,
                                                     **kwargs)

  @staticmethod
  def __create_name_version_map(api_services):
    """Create a map from API name/version to Service class/factory.

    This creates a map from an API name and version to a list of remote.Service
    factories that implement that API.

    Args:
      api_services: A list of remote.Service-derived classes or factories
        created with remote.Service.new_factory.

    Returns:
      A mapping from (api name, api version) to a list of service factories,
      for service classes that implement that API.

    Raises:
      ApiConfigurationError: If a Service class appears more than once
        in api_services.
    """
    api_name_version_map = {}
    for service_factory in api_services:
      try:
        service_class = service_factory.service_class
      except AttributeError:
        service_class = service_factory
        service_factory = service_class.new_factory()

      key = service_class.api_info.name, service_class.api_info.api_version
      service_factories = api_name_version_map.setdefault(key, [])
      if service_factory in service_factories:
        raise api_config.ApiConfigurationError(
            'Can\'t add the same class to an API twice: %s' %
            service_factory.service_class.__name__)

      service_factories.append(service_factory)
    return api_name_version_map

  @staticmethod
  def __register_services(api_name_version_map, api_config_registry):
    """Register & return a list of each URL and class that handles that URL.

    This finds every service class in api_name_version_map, registers it with
    the given ApiConfigRegistry, builds the URL for that class, and adds
    the URL and its factory to a list that's returned.

    Args:
      api_name_version_map: A mapping from (api name, api version) to a list of
        service factories, as returned by __create_name_version_map.
      api_config_registry: The ApiConfigRegistry where service classes will
        be registered.

    Returns:
      A list of (URL, service_factory) for each service class in
      api_name_version_map.

    Raises:
      ApiConfigurationError: If a Service class appears more than once
        in api_name_version_map.  This could happen if one class is used to
        implement multiple APIs.
    """
    generator = api_config.ApiConfigGenerator()
    protorpc_services = []
    for service_factories in api_name_version_map.values():
      service_classes = [service_factory.service_class
                         for service_factory in service_factories]
      config_dict = generator.get_config_dict(service_classes)
      api_config_registry.register_backend(config_dict)

      for service_factory in service_factories:
        protorpc_class_name = service_factory.service_class.__name__
        root = '%s%s' % (service_factory.service_class.api_info.base_path,
                         protorpc_class_name)
        if any(service_map[0] == root or service_map[1] == service_factory
               for service_map in protorpc_services):
          raise api_config.ApiConfigurationError(
              'Can\'t reuse the same class in multiple APIs: %s' %
              protorpc_class_name)
        protorpc_services.append((root, service_factory))
    return protorpc_services

  def __is_json_error(self, status, headers):
    """Determine if response is an error.

    Args:
      status: HTTP status code.
      headers: Dictionary of (lowercase) header name to value.

    Returns:
      True if the response was an error, else False.
    """
    content_header = headers.get('content-type', '')
    content_type, unused_params = cgi.parse_header(content_header)
    return (status.startswith('400') and
            content_type.lower() in _ALL_JSON_CONTENT_TYPES)

  def __write_error(self, status_code, error_message=None):
    """Return the HTTP status line and body for a given error code and message.

    Args:
      status_code: HTTP status code to be returned.
      error_message: Error message to be returned.

    Returns:
      Tuple (http_status, body):
        http_status: HTTP status line, e.g. 200 OK.
        body: Body of the HTTP request.
    """
    if error_message is None:
      error_message = http_client.responses[status_code]
    status = '%d %s' % (status_code, http_client.responses[status_code])
    message = EndpointsErrorMessage(
        state=EndpointsErrorMessage.State.APPLICATION_ERROR,
        error_message=error_message)
    return status, self.__PROTOJSON.encode_message(message)

  def protorpc_to_endpoints_error(self, status, body):
    """Convert a ProtoRPC error to the format expected by Google Endpoints.

    If the body does not contain an ProtoRPC message in state APPLICATION_ERROR
    the status and body will be returned unchanged.

    Args:
      status: HTTP status of the response from the backend
      body: JSON-encoded error in format expected by Endpoints frontend.

    Returns:
      Tuple of (http status, body)
    """
    try:
      rpc_error = self.__PROTOJSON.decode_message(remote.RpcStatus, body)
    except (ValueError, messages.ValidationError):
      rpc_error = remote.RpcStatus()

    if rpc_error.state == remote.RpcStatus.State.APPLICATION_ERROR:

      # Try to map to HTTP error code.
      error_class = _ERROR_NAME_MAP.get(rpc_error.error_name)
      if error_class:
        status, body = self.__write_error(error_class.http_status,
                                          rpc_error.error_message)
    return status, body

  def get_api_configs(self):
    return {
        'items': self.api_config_registry.all_api_configs()}

  def __call__(self, environ, start_response):
    """Wrapper for the Endpoints server app.

    Args:
      environ: WSGI request environment.
      start_response: WSGI start response function.

    Returns:
      Response from service_app or appropriately transformed error response.
    """
    # Call the ProtoRPC App and capture its response
    with util.StartResponseProxy() as start_response_proxy:
      body_iter = self.service_app(environ, start_response_proxy.Proxy)
      status = start_response_proxy.response_status
      headers = start_response_proxy.response_headers
      exception = start_response_proxy.response_exc_info

      # Get response body
      body = start_response_proxy.response_body
      # In case standard WSGI behavior is implemented later...
      if not body:
        body = ''.join(body_iter)

    # Transform ProtoRPC error into format expected by endpoints.
    headers_dict = dict([(k.lower(), v) for k, v in headers])
    if self.__is_json_error(status, headers_dict):
      status, body = self.protorpc_to_endpoints_error(status, body)
      # If the content-length header is present, update it with the new
      # body length.
      if 'content-length' in headers_dict:
        for index, (header_name, _) in enumerate(headers):
          if header_name.lower() == 'content-length':
            headers[index] = (header_name, str(len(body)))
            break

    start_response(status, headers, exception)
    return [body]


# Silence lint warning about invalid function name
# pylint: disable=g-bad-name
def api_server(api_services, **kwargs):
  """Create an api_server.

  The primary function of this method is to set up the WSGIApplication
  instance for the service handlers described by the services passed in.
  Additionally, it registers each API in ApiConfigRegistry for later use
  in the BackendService.getApiConfigs() (API config enumeration service).
  It also configures service control.

  Args:
    api_services: List of protorpc.remote.Service classes implementing the API
      or a list of _ApiDecorator instances that decorate the service classes
      for an API.
    **kwargs: Passed through to protorpc.wsgi.service.service_handlers except:
      protocols - ProtoRPC protocols are not supported, and are disallowed.

  Returns:
    A new WSGIApplication that serves the API backend and config registry.

  Raises:
    TypeError: if protocols are configured (this feature is not supported).
  """
  # Disallow protocol configuration for now, Lily is json-only.
  if 'protocols' in kwargs:
    raise TypeError("__init__() got an unexpected keyword argument 'protocols'")

  from . import _logger as endpoints_logger
  from . import __version__ as endpoints_version
  endpoints_logger.info('Initializing Endpoints Framework version %s', endpoints_version)

  # Construct the api serving app
  apis_app = _ApiServer(api_services, **kwargs)
  dispatcher = endpoints_dispatcher.EndpointsDispatcherMiddleware(apis_app)

  # Determine the service name
  service_name = os.environ.get('ENDPOINTS_SERVICE_NAME')
  if not service_name:
    _logger.warn('Did not specify the ENDPOINTS_SERVICE_NAME environment'
                 ' variable so service control is disabled.  Please specify'
                 ' the name of service in ENDPOINTS_SERVICE_NAME to enable'
                 ' it.')
    return dispatcher

  from endpoints_management.control import client as control_client
  from endpoints_management.control import wsgi as control_wsgi

  # If we're using a local server, just return the dispatcher now to bypass
  # control client.
  if control_wsgi.running_on_devserver():
    _logger.warn('Running on local devserver, so service control is disabled.')
    return dispatcher

  from endpoints_management import _logger as management_logger
  from endpoints_management import __version__ as management_version
  management_logger.info('Initializing Endpoints Management Framework version %s', management_version)

  # The DEFAULT 'config' should be tuned so that it's always OK for python
  # App Engine workloads.  The config can be adjusted, but that's probably
  # unnecessary on App Engine.
  controller = control_client.Loaders.DEFAULT.load(service_name)

  # Start the GAE background thread that powers the control client's cache.
  control_client.use_gae_thread()
  controller.start()

  return control_wsgi.add_all(
      dispatcher,
      app_identity.get_application_id(),
      controller)
