# Copyright 2008 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.

import base64
import hashlib
import hmac
import logging
import time
import zlib

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from django.http import HttpResponse
from froofle.protobuf.service import RpcController

from codereview.models import Account, Settings
from codereview.internal.util import InternalAPI
from codereview.view_util import xsrf_for, is_xsrf_ok

from codereview.review_service import ReviewServiceImp
from codereview.internal.admin_service import AdminServiceImp
from codereview.internal.build_service import BuildServiceImp
from codereview.internal.bundle_store_service import BundleStoreServiceImp
from codereview.internal.change_service import ChangeServiceImp
from codereview.internal.merge_service import MergeServiceImp

MAX_TIME_WINDOW = 5 * 60 # seconds
XSRF_PATH = '/proto/'
services = {}

def register_service(s_impl):
  services[s_impl.GetDescriptor().name] = s_impl

register_service(ReviewServiceImp())
register_service(AdminServiceImp())
register_service(BuildServiceImp())
register_service(BundleStoreServiceImp())
register_service(ChangeServiceImp())
register_service(MergeServiceImp())

class _LocalController(RpcController):
  def __init__(self, s_impl):
    self._failed = None
    self._service = s_impl

  def Reset(self):
    pass

  def Failed(self):
    pass

  def ErrorText(self):
    pass

  def StartCancel(self):
    pass

  def SetFailed(self, reason):
    logging.error("Failed on %s: %s" % (
      self._service.__class__.__name__,
      reason))
    self._failed = reason

  def IsCancelled(self):
    pass

  def NotifyOnCancel(self, callback):
    pass

  def HasFailed(self):
    return self._failed is not None

def token(req):
  user = users.get_current_user()
  if not user:
    return HttpResponse(status=401, content="User must be logged in.")
  return HttpResponse(content = xsrf_for(XSRF_PATH),
                      content_type = 'application/octet-stream')

def serve(req, service_name, action_name):
  try:
    type_str = req.META['CONTENT_TYPE']
  except KeyError:
    return HttpResponse(status=415, content="Invalid request body type")

  type = type_str.split('; ')
  type_dict = {}
  type_dict['name'] = None
  type_dict['compress'] = None
  for t in type[1:]:
    name, val = t.split('=', 1)
    type_dict[name] = val
  if type[0] != "application/x-google-protobuf":
    return HttpResponse(status=415, content="Invalid request body type")

  try: s_impl = services[service_name]
  except KeyError:
    return HttpResponse(status=404, content="Service not recognized.")

  method = s_impl.GetDescriptor().FindMethodByName(action_name)
  if not method:
    return HttpResponse(status=404, content="Method not recognized.")

  request = s_impl.GetRequestClass(method)()
  request_name = request.DESCRIPTOR.full_name
  if type_dict['name'] != request_name:
    return HttpResponse(status=415,
                        content="Expected a %s" % request_name)

  raw_body = req.raw_post_data
  msg_bin = raw_body

  if 'HTTP_CONTENT_MD5' in req.META:
    expmd5 = req.META['HTTP_CONTENT_MD5']

    actmd5 = hashlib.md5()
    actmd5.update(raw_body)
    actmd5 = base64.b64encode(actmd5.digest())

    if actmd5 != expmd5:
      return HttpResponse(status=412,
                          content="Content-MD5 incorrect")

  compression = type_dict['compress']
  if compression == 'deflate':
    msg_bin = zlib.decompress(msg_bin)
  elif compression:
    return HttpResponse(status=415,
                        content="Unsupported compression %s" % compression)

  if isinstance(s_impl, InternalAPI):
    key = Settings.get_settings().internal_api_key
    key = base64.b64decode(key)

    try:
      date = int(req.META['HTTP_X_DATE_UTC'])
    except KeyError:
      return HttpResponse(status=403,
                          content="X-Date-UTC header is required.")

    try:
      exp_sig = req.META['HTTP_AUTHORIZATION']
    except KeyError:
      return HttpResponse(status=403,
                          content="Authorization header is required.")

    if not exp_sig.startswith("proto :"):
      return HttpResponse(status=403,
                          content="Malformed authorization header.")
    exp_sig = exp_sig[len("proto :"):]

    now = time.time()
    if abs(date - now) > MAX_TIME_WINDOW:
      return HttpResponse(status=403,
                          content="Request is too early or too late.")

    m = hmac.new(key, digestmod=hashlib.sha1)
    m.update('POST %s\n' % req.path)
    m.update('X-Date-UTC: %s\n' % date)
    m.update('Content-Type: %s\n' % type_str)
    m.update('\n')
    m.update(raw_body)
    if base64.b64encode(m.digest()) != exp_sig:
      return HttpResponse(status=403,
                          content="Invalid request signature.")
  else:
    user = users.get_current_user()
    if not user:
      return HttpResponse(status=401, content="User must be logged in.")

    try:
      xsrf = req.META['HTTP_X_XSRF_TOKEN']
    except KeyError:
      return HttpResponse(status=403,
                          content="X-XSRF-Token header required.")
    if not is_xsrf_ok(req, path=XSRF_PATH, xsrf=xsrf):
      return HttpResponse(status=403,
                          content="X-XSRF-Token invalid.")

  request.ParseFromString(msg_bin)
  controller = _LocalController(s_impl)

  class result_caddy:
    _r = HttpResponse(status=500)
    def __call__(self, r):
      if r is not None:
        r_bin = r.SerializeToString()
        r_name = r.DESCRIPTOR.full_name
        r_type = "application/x-google-protobuf; name=%s" % r_name
        self._r = HttpResponse(content_type = r_type, content = r_bin)
  done = result_caddy()

  s_impl.http_request = req

  s_impl.CallMethod(method, controller, request, done)
  if controller.HasFailed():
    return HttpResponse(status=500)
  return done._r
