#
# 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 subprocess
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,
                 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 c in revlist:
          req.contained_object.append(c)
      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)
        else:
          reason = 'unknown error ' + str(rsp.status_code)
        raise UploadError(reason)
  finally:
    os.unlink(tmp_bundle)
