# 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.ext import db

from codereview import models
from codereview.models import gql

from merge_pb2 import MergeService
from pending_merge_pb2 import *
from post_merge_result_pb2 import *
from post_branch_update_pb2 import *
from util import InternalAPI, automatic_retry

from codereview import email

def _send_clean_merge_email(http_request, change):
  if not change.emailed_clean_merge:
    email.send_change_message(http_request, change,
                              "mails/clean_merge.txt", None)
    change.emailed_clean_merge = True
  
def _send_missing_dependency_merge_email(http_request, change):
  if not change.emailed_clean_merge:
    email.send_change_message(http_request, change,
                              "mails/missing_dependency.txt", None)
    change.emailed_missing_dependency = True

def _send_path_conflict_email(http_request, change):
  if not change.emailed_clean_merge:
    email.send_change_message(http_request, change,
                              "mails/path_conflict.txt", None)
    change.emailed_path_conflict = True


class InvalidBranchStatusError(Exception):
  """The branch cannot be updated in this way at this time."""

class MergeServiceImp(MergeService, InternalAPI):
  @automatic_retry
  def NextPendingMerge(self, rpc_controller, req, done):

    patchsets = []
    while not patchsets:
      branch = gql(models.Branch,
                  "WHERE status = 'NEEDS_MERGE'"
                  " ORDER BY merge_submitted").get()
      if branch is None:
        break
      patchsets = branch.begin_merge()

    rsp = PendingMergeResponse()
    if patchsets:
      first = patchsets[0].change
      rsp.status_code = PendingMergeResponse.MERGE_READY
      rsp.dest_project_name = str(first.dest_project.name)
      rsp.dest_project_key = str(first.dest_project.key())
      rsp.dest_branch_name = str(first.dest_branch.name)
      rsp.dest_branch_key = str(first.dest_branch.key())
      for ps in patchsets:
        pmi = rsp.change.add()
        pmi.patchset_key = str(ps.key())
        pmi.revision_id = str(ps.revision.id)
    else:
      rsp.status_code = PendingMergeResponse.QUEUE_EMPTY
    done(rsp)

  @automatic_retry
  def PostMergeResult(self, rpc_controller, req, done):
    rsp = PostMergeResultResponse()

    success = []
    fail = []
    defer = []

    for ri in req.change:
      sc = ri.status_code
      ps = db.get(db.Key(ri.patchset_key))

      if ps.change.merged:
        success.append(ps)
        continue

      def chg_trans(key):
        change = db.get(key)
        if change.merge_patchset.key() != ps.key():
          return False

        if sc == MergeResultItem.CLEAN_MERGE:
          pass

        elif sc == MergeResultItem.ALREADY_MERGED:
          change.merged = True
          change.closed = True
          change.put()

        elif sc == MergeResultItem.MISSING_DEPENDENCY:
          pass

        elif sc == MergeResultItem.PATH_CONFLICT:
          change.unsubmit_merge()
          change.put()

        return True
      if db.run_in_transaction(chg_trans, ps.change.key()):
        if sc == MergeResultItem.CLEAN_MERGE:
          _send_clean_merge_email(self.http_request, ps.change)
          ps.change.put()

        elif sc == MergeResultItem.ALREADY_MERGED:
          success.append(ps)

        elif sc == MergeResultItem.MISSING_DEPENDENCY:
          _send_missing_dependency_merge_email(self.http_request, ps.change)
          ps.change.put()
          defer.append(ps)

        elif sc == MergeResultItem.PATH_CONFLICT:
          _send_path_conflict_email(self.http_request, ps.change)
          ps.change.put()
          fail.append(ps)
      else:
        fail.append(ps)

    branch = db.get(db.Key(req.dest_branch_key))
    branch.finish_merge(success, fail, defer)

    done(rsp)

  @automatic_retry
  def PostBranchUpdate(self, rpc_controller, req, done):
    rsp = PostBranchUpdateResponse()

    branch = db.get(db.Key(req.branch_key))
    merged = [db.get(db.Key(c_key)) for c_key in req.new_change]

    branch.merged(merged)

    for ps in merged:
      def trans(key):
        change = db.get(key)
        if change.merge_patchset.key() == ps.key():
          change.merged = True
          change.closed = True
          change.put()
      db.run_in_transaction(trans, ps.change.key())

    done(rsp)
