#!/usr/bin/env python3.8
#
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Manage submitting a large number of CLs."""

import argparse
import enum
import os
import re
import sys
import time

import ansi
import util
import gerrit_util

from typing import List, Dict, Tuple, Optional, Any, Callable

class ChangeStatus(enum.Enum):
  UNKNOWN = 1
  MISSING_VOTES = 2
  UNRESOLVED_COMMENTS = 3
  READY = 4
  TESTING = 5
  SUBMITTING = 6
  MERGED = 7

  def description(self) -> str:
    # Return a brief description of a CL's state.
    return {
        ChangeStatus.UNKNOWN: 'unknown',
        ChangeStatus.MISSING_VOTES: 'missing votes',
        ChangeStatus.UNRESOLVED_COMMENTS: 'comments',
        ChangeStatus.READY: 'ready',
        ChangeStatus.TESTING: 'testing',
        ChangeStatus.SUBMITTING: 'submitting',
        ChangeStatus.MERGED: 'merged',
    }[self]

  def color(self) -> Callable[[str], str]:
    """Return a color function from the ansi module for this status."""
    return {
        ChangeStatus.UNKNOWN: ansi.red,
        ChangeStatus.MISSING_VOTES: ansi.red,
        ChangeStatus.UNRESOLVED_COMMENTS: ansi.yellow,
        ChangeStatus.READY: ansi.green,
        ChangeStatus.TESTING: ansi.green,
        ChangeStatus.SUBMITTING: ansi.bright_green,
        ChangeStatus.MERGED: ansi.gray,
    }[self]

  def submit_error_description(self) -> Optional[str]:
    # Return an explanation of why this CL cannot be submitted.
    return {
        ChangeStatus.UNKNOWN: 'unknown error',
        ChangeStatus.MISSING_VOTES: 'CL is missing votes',
        ChangeStatus.UNRESOLVED_COMMENTS: 'CL has unresolved comments',
    }.get(self)



class Change:
  """A Gerrit Changelist."""

  def __init__(self, change_id: str, json: Any):
    self.change_id: str = change_id
    self.subject: str = json.get('subject', '<unknown>')
    self.id: int = int(json.get('_number', '-1'))
    self.json = json
    self.status_string: str = json.get('status', 'UNKNOWN')

  @classmethod
  def from_json(cls, json: Any) -> 'Change':
    return Change(json['change_id'], json=json)

  def labels(self) -> Dict[str, Any]:
    labels = self.json.get('labels', {})
    assert isinstance(labels, Dict)
    return labels

  def cq_votes(self) -> int:
    cq_labels = self.labels().get('Commit-Queue', {})
    if cq_labels.get('approved') is not None:
      return 2
    if cq_labels.get('recommended') is not None:
      return 1
    return 0

  def has_unresolved_comments(self) -> bool:
    unresolved_comments: int = self.json.get('unresolved_comment_count', 0)
    return unresolved_comments > 0

  def submittable(self) -> bool:
    is_submittable: bool = self.json.get('submittable', False)
    return is_submittable

  @property
  def status(self) -> ChangeStatus:
    """Return a CL's status."""
    # We expect a CL to either be 'NEW' or 'MERGED'.
    if self.status_string == 'MERGED':
      return ChangeStatus.MERGED
    if self.status_string != 'NEW':
      return ChangeStatus.UNKNOWN

    if not self.submittable():
      return ChangeStatus.MISSING_VOTES
    if self.has_unresolved_comments():
      return ChangeStatus.UNRESOLVED_COMMENTS
    if self.cq_votes() == 1:
      return ChangeStatus.TESTING
    if self.cq_votes() == 2:
      return ChangeStatus.SUBMITTING
    return ChangeStatus.READY


class GerritServer:
  """A connection to a Gerrit server."""

  DEFAULT_PARAMS = [
      'LABELS', 'ALL_REVISIONS', 'SKIP_DIFFSTAT', 'SUBMITTABLE', 'CHECK'
  ]

  def __init__(self, host: str):
    """Create a connection to the server."""
    self.host = host

  def query(self, query: List[Tuple[str, str]]) -> List[Change]:
    """Query a Gerrit server for changes matching query terms.

    Args:
      query: A list of key:value pairs for search parameters, as documented
        here (e.g. ('is', 'owner') for a parameter 'is:owner'):
        https://gerrit-review.googlesource.com/Documentation/user-search.html#search-operators

    Returns:
      JSON
    """
    return [Change.from_json(x) for x in gerrit_util.QueryChanges(
        self.host, query, o_params=GerritServer.DEFAULT_PARAMS)]

  def fetch_change(self, id: str) -> Optional[Change]:
    """Fetch information about the CL with the given Gerrit ID."""
    result = self.query([('change', id)])
    if len(result) == 1:
      return result[0]
    if len(result) > 1:
      raise Exception('More than one CL had the specified change ID.')
    return None

  def set_cq_state(self, id: str, state: int) -> None:
    """Update the 'Commit-Queue' label to the given vote."""
    gerrit_util.SetReview(
        self.host, id, labels={'Commit-Queue': state}, notify=False)

  def get_change_dependencies(self, id: str) -> List[str]:
    """Get a list of IDs that are dependencies of the given change."""
    # Get related change sets. This includes both children and parent changes.
    json: Any = gerrit_util.GetRelatedChanges(self.host, id)

    # Changes are given in topological order, from newest to oldest.
    #
    # Search through the changes until we see ourselves. Any later changes are dependencies.
    dependencies: List[str] = []
    seen_self = False
    for change in json.get('changes', []):
      # Ignore children of ourselves.
      change_id: str = change['change_id']
      if change_id == id:
        seen_self = True
      if not seen_self:
        continue
      dependencies.append(change_id)
    if not seen_self:
      return [id]
    return dependencies


def should_submit(cl: Change, abort_on_unresolved_comments: bool = True) -> bool:
  if not cl.submittable():
    return False
  if abort_on_unresolved_comments and cl.has_unresolved_comments():
    return False
  return True


def shorten(s: str, max_len: int = 60) -> str:
  """Truncate a long string, appending '...' if a change is made."""
  if len(s) < max_len:
    return s
  return s[:max_len-3] + '...'


def print_changes(results: List[Change]) -> None:
  """Display a list of results in a table."""
  print()
  print('%20s  %-10s  %-65s' % ('Status', 'CL Number', 'Subject'))
  print('%20s  %-10s  %-65s' % ('――――――', '――――――――――', '―――――――'))
  for result in results:
    status = result.status
    print('%s  %s  %s' % (status.color()('%20s' % status.description()), '%-10s' %
                          result.id, '%-65s' % shorten(result.subject, 65)))
  print()


class SubmitError(Exception):
  def __init__(self, message: str):
    self.message: str = message
    super().__init__(message)


def ensure_changes_submittable(
    changes: List[Change],
    abort_on_unresolved_comments: bool = True,
) -> None:
  """Ensure that the given list of changes are submittable."""
  for cl in changes:
    if cl.status != ChangeStatus.MERGED and not should_submit(cl, abort_on_unresolved_comments):
      raise SubmitError("CL %d can not be submitted: %s" % (
          cl.id, cl.status.submit_error_description() or "unknown error"))


def submit_changes(
    clock: util.Clock,
    server: GerritServer,
    changes: List[Change],
    num_retries: int = 0
) -> bool:
  # Strip out merged changes.
  changes = [cl for cl in changes if cl.status != ChangeStatus.MERGED]

  # For any CL that doesn't have a CQ+1, run it now to speed things up.
  # As long as the CL isn't changed in the mean-time, it won't be tested
  # again when we finally get around to +2'ing it.
  #
  # We ignore the first one, because we are just about to +2 it anyway.
  for cl in changes[1:]:
    if cl.cq_votes() == 0:
      print("Setting CQ state of CL %d to dry-run." % cl.id)
      server.set_cq_state(cl.change_id, 1)

  # Submit the changes in order.
  for cl in changes:
    backoff = util.ExponentialBackoff(clock)
    max_attempts = num_retries + 1
    num_attempts = 0
    print()
    print("Submitting CL %d: %s" % (cl.id, cl.subject))

    # If the CL was already CQ+2'ed when we started, treat this as one of our attempts.
    if cl.cq_votes() == 2:
      num_attempts += 1

    while True:
      # Fetch the latest information about the CL.
      current_cl = server.fetch_change(cl.change_id)

      # Check it still exists.
      if current_cl is None:
        raise SubmitError("CL %s could not be found." % cl.id)

      # If it is merged, we are done.
      if current_cl.status == ChangeStatus.MERGED:
        break

      # If it is not in CQ, add it to CQ.
      if current_cl.cq_votes() < 2:
        if num_attempts == 0:
          print(ansi.gray("  Adding to CQ."))
        elif num_attempts < max_attempts:
          print(ansi.yellow("  CL failed in CQ. Retrying..."))
        else:
          print(ansi.red("  CL failed in CQ. Aborting."))
          return False
        num_attempts += 1
        server.set_cq_state(cl.change_id, 2)

      # wait.
      backoff.wait()
      print(ansi.gray('  Polling...'))

    # Did we fail?
    print(ansi.green("  Submitted!"))

  return True


def parse_args() -> Any:
  description = r"""
Submit a chain of CLs, specified by giving the CL number of the end of the
chain. The command will poll indefinitely until the chain is submitted or an
error is detected.

The tool can be safely cancelled at any time. When restarted, it will resume
where it left off.

For example, given a chain of three CLs:

  101: Start hacking on 'foo'.
  102: More hacking on 'foo'.
  103: Finish hacking on 'foo'.

The command:

  fx gerrit-submit 103

will:

  1. Add a CQ+1 vote to all the CLs, to start testing them.
  2. Add a CQ+2 vote for the first CL, and wait for it to be submitted.
  3. Add a CQ+2 vote for the second CL, and wait for it to be submitted.
  4. Add a CQ+2 vote for the last CL, and wait for it to be submitted.

Adding a CQ+1 to every CL at the beginning speeds up submission: CQ won't
need to re-test intermediate CLs if they are not modified in the meantime.

If any CL is not ready to submit (for example, it is missing a vote, or has
unresolved comments), the tool will abort early.

By default, the tool will use the "fuchsia-review.googlesource.com" Gerrit
instances. Other instances can be specified using the "--host" parameter:

   fx gerrit-submit --host myteam-review.googlesource.com 12345

"""
  parser = argparse.ArgumentParser(
          description=description,
          formatter_class=argparse.RawDescriptionHelpFormatter)
  parser.add_argument('cl', metavar='CL',
                      help='Gerrit CL to submit. May either be a CL '
                           'number or Gerrit Change-ID.')
  parser.add_argument('--host', dest='host',
                      help='Gerrit host to connect to. '
                           'Defaults to "fuchsia-review.googlesource.com".',
                      default='fuchsia-review.googlesource.com')
  parser.add_argument('--num-retries', metavar='N', type=int, default=0,
                      help='number of times to retry a failed submission. '
                           'Defaults to 0.')
  parser.add_argument('-n', '--dry-run', action='store_true',
                      help='If specified, show the set of CLs that would '
                           'be submitted, but don''t actually submit.')
  parser.add_argument('-t', '--batch', action='store_true',
                      help='If specified, don''t prompt before starting '
                           'submit.')
  parser.add_argument('--ignore-comments', action='store_true',
                      help='If specified, allow submission of CLs that still '
                           'have unresolved comments on them.')
  return parser.parse_args()


def is_valid_change_id(value: str) -> bool:
  """Determine if "value" is a valid Gerrit CL identifier."""

  # Match strings of the form I609f446e6721dd95624939dd041189052054fb83
  if re.fullmatch('I[a-f0-9]{8,}', value):
    return True

  # Match plain integer change IDs.
  if re.fullmatch('[1-9][0-9]*', value):
    return True

  return False


def should_continue() -> bool:
  """Prompt the user to determine if an action should continue."""
  val = input('Submit CLs? [y/N] ')
  if val.lower()[:1] == 'y':
    return True

  print('Aborting.')
  return False


def main() -> int:
  # Parse and validate arguments.
  args = parse_args()

  # Ensure the Change-ID looks like a Gerrit Change-ID, and not a git commit.
  #
  # TODO: Support Git commit ids and ranges as well.
  if not is_valid_change_id(args.cl):
    print("The argument '%s' does not look like a valid Gerrit Change ID." % args.cl)
    print()
    print('Please provide either the numeric CL number (such as 12345) or\n'
          'the Change-ID found at the bottom of the CL description (such as\n'
          "'I0123456789abcdef0123456789abcdef0123456789abcdef'")
    return 1

  # Check we have valid authentication tokens.
  gerrit_util.EnsureAuthenticated(args.host)

  # Get the specified change, and bail out if we can't find it.
  server = GerritServer(args.host)
  specified_change = server.fetch_change(args.cl)
  if specified_change is None:
      print("Could not find Gerrit commit with id '%s'." % args.cl)
      return 1

  # Fetch the list of dependent CLs, and reverse into the order we need to
  # submit it in.
  change_ids = server.get_change_dependencies(specified_change.change_id)
  change_ids.reverse()

  # Fetch CL details.
  changes = []
  for change_id in change_ids:
    change = server.fetch_change(change_id)
    if change is None:
      print("Could not find CL with id '%s'." % change_id)
      return 1
    changes.append(change)

  # Print the set of changes.
  print_changes(changes)

  # Ensure we can submit the chain.
  ensure_changes_submittable(changes, abort_on_unresolved_comments=not args.ignore_comments)

  # Stop here on dry-run.
  if args.dry_run:
    return 0

  # Ask user to confirm.
  if not args.batch and not should_continue():
    return 0

  # Submit the changes.
  success = submit_changes(util.Clock(), server, changes, num_retries=args.num_retries)
  if not success:
    return 1

  # Success
  print()
  print('All changes submitted.')
  return 0


if __name__ == '__main__':
  try:
    sys.exit(main())
  except SubmitError as e:
    print('Error: %s' % e.message)
  except gerrit_util.GerritError as e:
    print('Error: %s' % e.message)
  sys.exit(1)

