# 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 codereview import models

from change_pb2 import ChangeService
from complete_patchset_pb2 import *
from upload_patchset_file_pb2 import *
from submit_change_pb2 import *
from util import *

class ChangeServiceImp(ChangeService, InternalAPI):

  @automatic_retry
  def SubmitChange(self, rpc_controller, req, done):
    rsp = SubmitChangeResponse()

    user = users.User(req.owner)
    branch = db.get(db.Key(req.dest_branch_key))
    if not branch:
      rsp.status_code = SubmitChangeResponse.UNKNOWN_BRANCH
      done(rsp)

    rev = commit_to_revision(branch.project, req.commit)
    if rev.patchset:
      rsp.status_code = SubmitChangeResponse.PATCHSET_EXISTS
      done(rsp)

    subject = u(req.commit.subject)[0:100]

    def trans():
      change = models.Change(
                 subject = subject,
                 description = u(req.commit.message),
                 owner = user,
                 dest_project = branch.project,
                 dest_branch = branch,
                 n_patchsets = 1)
      change.put()

      patchset = models.PatchSet(
                   change = change,
                   owner = user,
                   parent = change,
                   revision = rev,
                   id = 1)
      patchset.put()
      return (change, patchset)
    change, patchset = db.run_in_transaction(trans)

    if rev.link_patchset(patchset):
      rsp.status_code = SubmitChangeResponse.CREATED
      rsp.change_id = change.key().id()
      rsp.patchset_id = patchset.id
      rsp.patchset_key = str(patchset.key())
    else:
      db.delete([change, patchset])
      rsp.status_code = SubmitChangeResponse.PATCHSET_EXISTS
    done(rsp)

  @automatic_retry
  def UploadPatchsetFile(self, rpc_controller, req, done):
    rsp = UploadPatchsetFileResponse()

    patchset = db.get(db.Key(req.patchset_key))
    if not patchset:
      rsp.status_code = UploadPatchsetFileResponse.UNKNOWN_PATCHSET
      done(rsp)
      return

    if patchset.complete or patchset.change.closed:
      rsp.status_code = UploadPatchsetFileResponse.CLOSED
      done(rsp)
      return

    if UploadPatchsetFileRequest.ADD == req.status:
      status = 'A'
    elif UploadPatchsetFileRequest.MODIFY == req.status:
      status = 'M'
    elif UploadPatchsetFileRequest.DELETE == req.status:
      status = 'D'
    else:
      status = '?'

    try:
      if req.base_id:
        old_data = models.DeltaContent.create_content(
                     id = req.base_id,
                     text_z = req.base_z)
        new_data = models.DeltaContent.create_content(
                     id = req.final_id,
                     text_z = req.patch_z,
                     base = old_data)
        if new_data.text_z == req.patch_z:
          diff_data = new_data
        else:
          diff_data = models.DeltaContent.create_patch(
                        id = req.patch_id,
                        text_z = req.patch_z)
      else:
        old_data = None
        new_data = None
        diff_data = models.DeltaContent.create_patch(
                      id = req.patch_id,
                      text_z = req.patch_z)
    except models.DeltaPatchingException:
      logging.error("Patch error on change %s, patch set %s, file %s"
        % (patchset.change.key().id(),
           str(patchset.id),
           u(req.file_name))
      )
      rsp.status_code = UploadPatchsetFileResponse.PATCHING_ERROR
      done(rsp)
      return

    patch = models.Patch.get_or_insert_patch(
              patchset = patchset,
              filename = u(req.file_name),
              status = status,
              n_comments = 0,
              old_data = old_data,
              new_data = new_data,
              diff_data = diff_data)

    if old_data:
      models.CachedDeltaContent.get(old_data.key())
      models.CachedDeltaContent.get(new_data.key())
      if diff_data != new_data:
        models.CachedDeltaContent.get(diff_data.key())
    else:
      models.CachedDeltaContent.get(diff_data.key())

    rsp.status_code = UploadPatchsetFileResponse.CREATED
    done(rsp)

  @automatic_retry
  def CompletePatchset(serlf, rpc_controller, req, done):
    rsp = CompletePatchsetResponse()

    patchset = db.get(db.Key(req.patchset_key))
    if not patchset.complete:
      patchset.complete = True
      patchset.put()

      if len(req.compressed_filenames) > 0:
        models.PatchSetFilenames.store_compressed(
          patchset,
          req.compressed_filenames)
    done(rsp)
