# Copyright (c) 2020, the Dart project authors. All rights reserved. Use of this
# source code is governed by a BSD-style license that can be found in the
# LICENSE file.

from recipe_engine import recipe_api

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.go.chromium.org.luci.buildbucket.proto import builds_service as builds_service_pb2


class BisectApi(recipe_api.RecipeApi):
  REASON_SUCCESS = 'SUCCESS'
  FETCH_BUILDS_STEP_NAME = 'list previous builds'
  FIND_BASE_BUILD_STEP_NAME = 'find bisection base build'

  def _get_reason(self):
    return self.m.properties['bisect_reason']

  def get_base_build(self):
    return self.m.properties['bisect_base_build']

  def is_bisecting(self):
    return 'bisect_reason' in self.m.properties

  @property
  def is_enabled(self):  # pragma: no cover
    return self.m.properties.get('bisection_enabled', False)

  def schedule(self, repo_url, reason, is_experimental=False):
    if self.is_bisecting():
      base_build = self.get_base_build()
      bisect_reason = self._get_reason()
      assert bisect_reason != self.REASON_SUCCESS
      if bisect_reason == reason:
        self._bisect_older(bisect_reason, is_experimental, base_build)
      elif reason == self.REASON_SUCCESS:
        self._bisect_newer(bisect_reason, is_experimental, base_build)
      else:
        self._bisect_newer(bisect_reason, is_experimental, base_build)
        # The build failed for a different reason, fan out to find the root
        # cause of that failure as well.
        self._bisect_older(reason, is_experimental, base_build)
    else:
      self._start_bisection(repo_url, reason, is_experimental)

  def _find_base_build(self):
    """ Returns the most recent regular build if that build was successful,
        and `None` otherwise. """
    builder = self.m.buildbucket.build.builder
    create_time = common_pb2.TimeRange(
        end_time=self.m.buildbucket.build.create_time)
    search_predicate = builds_service_pb2.BuildPredicate(
        builder=builder, create_time=create_time)
    result = self.m.buildbucket.search(
        search_predicate, limit=100, step_name=BisectApi.FETCH_BUILDS_STEP_NAME)
    if not result:
      # No builds found.
      return None
    for candidate in result:
      if 'bisect_reason' not in candidate.output.properties:
        if candidate.status == common_pb2.SUCCESS:
          # Found a matching build.
          return candidate
        # The previous regular build was not successful, do not start a
        # bisection.
        return None
    return None

  def _start_bisection(self, repo_url, reason, is_experimental):
    current_rev = self.m.buildbucket.gitiles_commit.id
    if not current_rev:
      return

    with self.m.step.nest(BisectApi.FIND_BASE_BUILD_STEP_NAME):
      previous_build = self._find_base_build()
    if not previous_build:
      return
    base_build = previous_build.number

    previous_rev = previous_build.output.properties['got_revision']
    assert previous_rev, "Build does not have a commit"

    commits, _ = self.m.gitiles.log(
        url=repo_url, ref='%s..%s' % (previous_rev, current_rev))
    commits = commits[1:]  # The first commit is the current_rev
    commits = [commit['commit'] for commit in commits]
    self._bisect(commits, reason, is_experimental, base_build)

  def _bisect(self, commits, reason, is_experimental, base_build):
    if len(commits) == 0:
      # Nothing more to bisect.
      return

    middle_index = len(commits) // 2
    newer = commits[:middle_index]
    middle = commits[middle_index]
    older = commits[middle_index + 1:]

    commit = self.m.buildbucket.gitiles_commit
    middle_commit = common_pb2.GitilesCommit()
    middle_commit.CopyFrom(commit)
    middle_commit.id = middle
    builder = self.m.buildbucket.build.builder
    properties = {
        'bisection_enabled': True,
        'bisect_newer': newer,
        'bisect_older': older,
        'bisect_reason': reason,
        'bisect_base_build': base_build,
    }
    schedule_experimental = (
        True if is_experimental else self.m.buildbucket.INHERIT)
    request = self.m.buildbucket.schedule_request(
        builder=builder.builder,
        project=builder.project,
        bucket=builder.bucket,
        properties=properties,
        gitiles_commit=middle_commit,
        inherit_buildsets=False,
        experimental=schedule_experimental,
    )
    self.m.buildbucket.schedule([request],
                                step_name='schedule bisect (%s)' % middle)

  def _bisect_newer(self, reason, is_experimental, base_build):
    self._bisect(
        list(self.m.properties.get('bisect_newer', [])), reason,
        is_experimental, base_build)

  def _bisect_older(self, reason, is_experimental, base_build):
    self._bisect(
        list(self.m.properties.get('bisect_older', [])), reason,
        is_experimental, base_build)
