# 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 logging

from google.appengine.api import users
from google.appengine.ext import db

from models import gql, Project, Branch, Account
import git_models

from review_pb2 import *
from upload_bundle_pb2 import *
from internal.util import automatic_retry

class ReviewServiceImp(ReviewService):
  """
    Implements the review_service API for developer clients.
  """

  @automatic_retry
  def UploadBundle(self, rpc_controller, req, done):
    """
      Receives an uploaded Git style bundle and queues it for processing.
    """
    rsp = UploadBundleResponse()

    # can't get here if there isn't a current user
    current_user = users.get_current_user()
    
    if not Account.get_account_for_user(current_user).cla_verified:
      rsp.status_code = UploadBundleResponse.UNAUTHORIZED_USER
      done(rsp)
      return

    if not req.dest_project:
      rsp.status_code = UploadBundleResponse.UNKNOWN_PROJECT
      done(rsp)
      return

    proj = req.dest_project
    if proj.endswith(".git"):
      proj = proj[0 : len(proj) - 4]

    proj = Project.get_project_for_name(proj)
    if not proj:
      rsp.status_code = UploadBundleResponse.UNKNOWN_PROJECT
      done(rsp)
      return

    if not req.dest_branch:
      rsp.status_code = UploadBundleResponse.UNKNOWN_BRANCH
      done(rsp)

    brch = Branch.get_branch_for_name(proj, req.dest_branch)
    if not brch:
      rsp.status_code = UploadBundleResponse.UNKNOWN_BRANCH
      done(rsp)
      return

    rb = git_models.ReceivedBundle(
      dest_project = proj,
      dest_branch = brch,
      owner = current_user,
      state = git_models.ReceivedBundle.STATE_UPLOADING,
      contained_objects = list(req.contained_object))
    rb.put()

    rsp.bundle_id = str(rb.key().id())
    self._store_segment(req, rsp, rb, 1)
    done(rsp)

  @automatic_retry
  def ContinueBundle(self, rpc_controller, req, done):
    rsp = UploadBundleResponse()
    rsp.bundle_id = req.bundle_id

    rb = git_models.ReceivedBundle.get_by_id(int(req.bundle_id))
    if rb is None:
      rsp.status_code = UploadBundleResponse.UNKNOWN_BUNDLE
      done(rsp)
      return

    if rb.owner != users.get_current_user():
      rsp.status_code = UploadBundleResponse.NOT_BUNDLE_OWNER
      done(rsp)
      return

    self._store_segment(req, rsp, rb, req.segment_id)
    done(rsp)

  def _store_segment(self, req, rsp, rb, segment_id):
    rb.set_segment(segment_id, req.bundle_data)
    def trans():
      b = db.get(rb.key())
      if b.state != git_models.ReceivedBundle.STATE_UPLOADING:
        return False

      if b.n_segments < segment_id:
        b.n_segments = segment_id
      if not req.partial_upload:
        b.state = git_models.ReceivedBundle.STATE_NEW
      b.put()
      return True

    if db.run_in_transaction(trans):
      if req.partial_upload:
        rsp.status_code = UploadBundleResponse.CONTINUE
      else:
        rb.ready()
        rsp.status_code = UploadBundleResponse.RECEIVED
    else:
      rsp.status_code = UploadBundleResponse.BUNDLE_CLOSED

