#!/usr/bin/env python2.7
#
# Copyright 2007 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.
#
"""Proxy that dispatches Discovery requests to the prod Discovery service."""



import httplib
import json
import logging


class DiscoveryApiProxy(object):
  """Proxies discovery service requests to a known cloud endpoint."""

  # The endpoint host we're using to proxy discovery and static requests.
  # Using separate constants to make it easier to change the discovery service.
  _DISCOVERY_PROXY_HOST = 'webapis-discovery.appspot.com'
  _STATIC_PROXY_HOST = 'webapis-discovery.appspot.com'
  _DISCOVERY_API_PATH_PREFIX = '/_ah/api/discovery/v1/'

  def _dispatch_request(self, path, body):
    """Proxies GET request to discovery service API.

    Args:
      path: A string containing the URL path relative to discovery service.
      body: A string containing the HTTP POST request body.

    Returns:
      HTTP response body or None if it failed.
    """
    full_path = self._DISCOVERY_API_PATH_PREFIX + path
    headers = {'Content-type': 'application/json'}
    connection = httplib.HTTPSConnection(self._DISCOVERY_PROXY_HOST)
    try:
      connection.request('POST', full_path, body, headers)
      response = connection.getresponse()
      response_body = response.read()
      if response.status != 200:
        logging.error('Discovery API proxy failed on %s with %d.\r\n'
                      'Request: %s\r\nResponse: %s',
                      full_path, response.status, body, response_body)
        return None
      return response_body
    finally:
      connection.close()

  def generate_discovery_doc(self, api_config, api_format):
    """Generates a discovery document from an API file.

    Args:
      api_config: A string containing the .api file contents.
      api_format: A string, either 'rest' or 'rpc' depending on the which kind
        of discvoery doc is requested.

    Returns:
      The discovery doc as JSON string.

    Raises:
      ValueError: When api_format is invalid.
    """
    if api_format not in ['rest', 'rpc']:
      raise ValueError('Invalid API format')
    path = 'apis/generate/' + api_format
    request_dict = {'config': json.dumps(api_config)}
    request_body = json.dumps(request_dict)
    return self._dispatch_request(path, request_body)

  def generate_directory(self, api_configs):
    """Generates an API directory from a list of API files.

    Args:
      api_configs: A list of strings which are the .api file contents.

    Returns:
      The API directory as JSON string.
    """
    request_dict = {'configs': api_configs}
    request_body = json.dumps(request_dict)
    return self._dispatch_request('apis/generate/directory', request_body)

  def get_static_file(self, path):
    """Returns static content via a GET request.

    Args:
      path: A string containing the URL path after the domain.

    Returns:
      A tuple of (response, response_body):
        response: A HTTPResponse object with the response from the static
          proxy host.
        response_body: A string containing the response body.
    """
    connection = httplib.HTTPSConnection(self._STATIC_PROXY_HOST)
    try:
      connection.request('GET', path, None, {})
      response = connection.getresponse()
      response_body = response.read()
    finally:
      connection.close()
    return response, response_body
