# 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'

  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

  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 _start_bisection(self, repo_url, reason, is_experimental):
    current_rev = self.m.buildbucket.gitiles_commit.id
    if not current_rev:
      return

    # Search for previous builds created by the Luci scheduler (to exclude
    # bisection builds). The TimeRange includes all builds from start_time
    # (defaults to 0) to end_time (exclusive). Because builds are ordered by
    # create_time, the first result will be the previous build.
    create_time = common_pb2.TimeRange(
        end_time=self.m.buildbucket.build.create_time)
    builder = self.m.buildbucket.build.builder
    search_predicate = builds_service_pb2.BuildPredicate(
        builder=builder,
        create_time=create_time,
        tags=[common_pb2.StringPair(key='user_agent', value='luci-scheduler')])
    result = self.m.buildbucket.search(
        search_predicate, limit=1, step_name='fetch previous build')
    if not result or len(result) == 0:
      # There is no previous build: do not bisect on new builders.
      return
    previous_build = result[0]
    if previous_build.status == common_pb2.FAILURE:
      # Do not bisect if the previous build failed.
      # TODO(athom): Check if the failure reason is the same by adding
      #              'builds.*.summaryMarkdown' to the field mask.
      return
    previous_rev = previous_build.input.gitiles_commit.id
    # We're intentionally not paging through the log to avoid bisecting an
    # excessive number of commits.
    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]
    base_build = previous_build.number
    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)
