#
# Copyright (C) 2008 The Android Open Source Project
#
# 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 getpass
import os
import sys
from tempfile import mkstemp

from codereview.proto_client import HttpRpc, Proxy
from codereview.review_pb2 import ReviewService_Stub
from codereview.upload_bundle_pb2 import *
from git_command import GitCommand
from error import UploadError

try:
  import readline
except ImportError:
  pass

MAX_SEGMENT_SIZE = 1020 * 1024

def _GetRpcServer(email, server, save_cookies):
  """Returns an RpcServer.

  Returns:
    A new RpcServer, on which RPC calls can be made.
  """

  def GetUserCredentials():
    """Prompts the user for a username and password."""
    e = email
    if e is None:
      e = raw_input("Email: ").strip()
    password = getpass.getpass("Password for %s: " % e)
    return (e, password)

  # If this is the dev_appserver, use fake authentication.
  lc_server = server.lower()
  if lc_server == "localhost" or lc_server.startswith("localhost:"):
    if email is None:
      email = "test@example.com"
    server = HttpRpc(
        server,
        lambda: (email, "password"),
        extra_headers={"Cookie":
                       'dev_appserver_login="%s:False"' % email})
    # Don't try to talk to ClientLogin.
    server.authenticated = True
    return server

  if save_cookies:
    cookie_file = ".gerrit_cookies"
  else:
    cookie_file = None

  return HttpRpc(server, GetUserCredentials,
                 cookie_file=cookie_file)

def UploadBundle(project,
                 server,
                 email,
                 dest_project,
                 dest_branch,
                 src_branch,
                 bases,
                 people,
                 replace_changes = None,
                 save_cookies=True):

  srv = _GetRpcServer(email, server, save_cookies)
  review = Proxy(ReviewService_Stub(srv))
  tmp_fd, tmp_bundle = mkstemp(".bundle", ".gpq")
  os.close(tmp_fd)

  srcid = project.bare_git.rev_parse(src_branch)
  revlist = project._revlist(src_branch, *bases)

  if srcid not in revlist:
    # This can happen if src_branch is an annotated tag
    #
    revlist.append(srcid)
  revlist_size = len(revlist) * 42

  try:
    cmd = ['bundle', 'create', tmp_bundle, src_branch]
    cmd.extend(bases)
    if GitCommand(project, cmd).Wait() != 0:
      raise UploadError('cannot create bundle')
    fd = open(tmp_bundle, "rb")

    bundle_id = None
    segment_id = 0
    next_data = fd.read(MAX_SEGMENT_SIZE - revlist_size)

    while True:
      this_data = next_data
      next_data = fd.read(MAX_SEGMENT_SIZE)
      segment_id += 1

      if bundle_id is None:
        req = UploadBundleRequest()
        req.dest_project = str(dest_project)
        req.dest_branch = str(dest_branch)
        for e in people[0]:
          req.reviewers.append(e)
        for e in people[1]:
          req.cc.append(e)
        for c in revlist:
          req.contained_object.append(c)
        if replace_changes:
          for change_id,commit_id in replace_changes.iteritems():
            r = req.replace.add()
            r.change_id = change_id
            r.object_id = commit_id
      else:
        req = UploadBundleContinue()
        req.bundle_id = bundle_id
        req.segment_id = segment_id

      req.bundle_data = this_data
      if len(next_data) > 0:
        req.partial_upload = True
      else:
        req.partial_upload = False

      if bundle_id is None:
        rsp = review.UploadBundle(req)
      else:
        rsp = review.ContinueBundle(req)

      if rsp.status_code == UploadBundleResponse.CONTINUE:
        bundle_id = rsp.bundle_id
      elif rsp.status_code == UploadBundleResponse.RECEIVED:
        bundle_id = rsp.bundle_id
        return bundle_id
      else:
        if rsp.status_code == UploadBundleResponse.UNKNOWN_PROJECT:
          reason = 'unknown project "%s"' % dest_project
        elif rsp.status_code == UploadBundleResponse.UNKNOWN_BRANCH:
          reason = 'unknown branch "%s"' % dest_branch
        elif rsp.status_code == UploadBundleResponse.UNKNOWN_BUNDLE:
          reason = 'unknown bundle'
        elif rsp.status_code == UploadBundleResponse.NOT_BUNDLE_OWNER:
          reason = 'not bundle owner'
        elif rsp.status_code == UploadBundleResponse.BUNDLE_CLOSED:
          reason = 'bundle closed'
        elif rsp.status_code == UploadBundleResponse.UNAUTHORIZED_USER:
          reason = ('Unauthorized user.  Visit http://%s/hello to sign up.'
                    % server)
        elif rsp.status_code == UploadBundleResponse.UNKNOWN_CHANGE:
          reason = 'invalid change id'
        elif rsp.status_code == UploadBundleResponse.CHANGE_CLOSED:
          reason = 'one or more changes are closed'
        elif rsp.status_code == UploadBundleResponse.UNKNOWN_EMAIL:
          emails = [x for x in rsp.invalid_reviewers] + [
                    x for x in rsp.invalid_cc]
          reason = 'invalid email addresses: %s' % ", ".join(emails)
        else:
          reason = 'unknown error ' + str(rsp.status_code)
        raise UploadError(reason)
  finally:
    os.unlink(tmp_bundle)
