# -*- coding: utf-8 -*-
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Fake CIDB for unit testing."""

from __future__ import print_function

import datetime

from chromite.lib import build_requests
from chromite.lib import constants
from chromite.lib import cidb
from chromite.lib import failure_message_lib


class FakeCIDBConnection(object):
  """Fake connection to a Continuous Integration database.

  This class is a partial re-implementation of CIDBConnection, using
  in-memory lists rather than a backing database.
  """

  NUM_RESULTS_NO_LIMIT = -1

  def __init__(self, fake_keyvals=None):
    self.buildTable = []
    self.clActionTable = []
    self.buildStageTable = {}
    self.failureTable = {}
    self.fake_time = None
    self.fake_keyvals = fake_keyvals or {}
    self.buildMessageTable = {}
    self.buildRequestTable = {}

  def _TrimStatus(self, status):
    """Trims a build row to keys that should be returned by GetBuildStatus"""
    return {k: v for (k, v) in status.items()
            if k in cidb.CIDBConnection.BUILD_STATUS_KEYS}

  def SetTime(self, fake_time):
    """Sets a fake time to be retrieved by GetTime.

    Args:
      fake_time: datetime.datetime object.
    """
    self.fake_time = fake_time

  def GetTime(self):
    """Gets the current database time."""
    return self.fake_time or datetime.datetime.now()

  def InsertBuild(self, builder_name, build_number,
                  build_config, bot_hostname, master_build_id=None,
                  timeout_seconds=None, status=constants.BUILDER_STATUS_PASSED,
                  important=None, buildbucket_id=None, milestone_version=None,
                  platform_version=None, start_time=None, build_type=None,
                  branch=None):
    """Insert a build row.

    Note this API slightly differs from cidb as we pass status to avoid having
    to have a later FinishBuild call in testing.
    """
    if start_time is None:
      start_time = datetime.datetime.now()

    deadline = None
    if timeout_seconds is not None:
      timediff = datetime.timedelta(seconds=timeout_seconds)
      deadline = start_time + timediff

    build_id = len(self.buildTable)
    row = {'id': build_id,
           'builder_name': builder_name,
           'buildbot_generation': constants.BUILDBOT_GENERATION,
           # While waterfall is nullable all non waterfall entries show empty
           # string, sticking to the convention.
           'waterfall': '',
           'build_number': build_number,
           'build_config' : build_config,
           'bot_hostname': bot_hostname,
           'start_time': start_time,
           'master_build_id' : master_build_id,
           'deadline': deadline,
           'status': status,
           'finish_time': start_time,
           'important': important,
           'buildbucket_id': buildbucket_id,
           'final': False,
           'milestone_version': milestone_version,
           'platform_version': platform_version,
           'build_type': build_type,
           'branch': branch}
    self.buildTable.append(row)
    return build_id

  def FinishBuild(self, build_id, status=None, summary=None, strict=True):
    """Update the build with finished status."""
    build = self.buildTable[build_id]

    if strict and build['final']:
      return 0

    values = {}
    if status is not None:
      values.update(status=status)
    if summary is not None:
      values.update(summary=summary)

    values.update(finish_time=datetime.datetime.now(), final=True)

    if values:
      build.update(values)
      return 1
    else:
      return 0

  def UpdateMetadata(self, build_id, metadata):
    """See cidb.UpdateMetadata.

    Args:
      build_id: The build to update.
      metadata: A cbuildbot metadata object. Or, a dictionary (note: using
                a dictionary is not supported by the base cidb API, but
                is provided for this fake class for ease of use in test
                set-up code).
    """
    d = metadata if isinstance(metadata, dict) else metadata.GetDict()
    versions = d.get('version') or {}
    self.buildTable[build_id].update(
        {'chrome_version': versions.get('chrome'),
         'milestone_version': versions.get('milestone'),
         'platform_version': versions.get('platform'),
         'full_version': versions.get('full'),
         'sdk_version': d.get('sdk-versions'),
         'toolchain_url': d.get('toolchain-url'),
         'build_type': d.get('build_type'),
         'important': d.get('important')})
    return 1

  def InsertBuildStage(self, build_id, name, board=None,
                       status=constants.BUILDER_STATUS_PLANNED):
    build_stage_id = len(self.buildStageTable)
    row = {'build_id': build_id,
           'name': name,
           'board': board,
           'status': status}
    self.buildStageTable[build_stage_id] = row
    return build_stage_id

  def InsertBoardPerBuild(self, build_id, board):
    # TODO(akeshet): Fill this placeholder.
    pass

  def InsertBuildMessage(self, build_id,
                         message_type=None, message_subtype=None,
                         message_value=None, board=None):
    """Insert a build message.

    Args:
      build_id: primary key of build recording this message.
      message_type: Optional str name of message type.
      message_subtype: Optional str name of message subtype.
      message_value: Optional value of message.
      board: Optional str name of the board.

    Returns:
      The build message id (string).
    """
    if message_type:
      message_type = message_type[:240]
    if message_subtype:
      message_subtype = message_subtype[:240]
    if message_value:
      message_value = message_value[:480]
    if board:
      board = board[:240]

    build_message_id = len(self.buildMessageTable)
    values = {'build_id': build_id,
              'message_type': message_type,
              'message_subtype': message_subtype,
              'message_value': message_value,
              'board': board}
    self.buildMessageTable[build_message_id] = values
    return build_message_id

  def InsertBuildRequests(self, build_reqs):
    """Insert a list of build requests.

    Args:
      build_reqs: A list of build_requests.BuildRequest instances.

    Returns:
      The number of inserted rows.
    """
    request_id = len(self.buildRequestTable)
    for build_req in build_reqs:
      values = {
          'id': request_id,
          'build_id': build_req.build_id,
          'request_build_config': build_req.request_build_config,
          'request_build_args': build_req.request_build_args,
          'request_buildbucket_id': build_req.request_buildbucket_id,
          'request_reason': build_req.request_reason,
          'timestamp': build_req.timestamp or datetime.datetime.now()}
      self.buildRequestTable[request_id] = values
      request_id = request_id + 1

    return len(build_reqs)

  def GetBuildMessages(self, build_id, message_type=None, message_subtype=None):
    """Get the build messages of the given build id.

    Args:
      build_id: build id (string) of the build to get messages.
      message_type: Get messages with the specific message_type (string) if
        message_type is not None.
      message_subtype: Get messages with the specific message_subtype (stirng)
        if message_subtype is not None.

    Returns:
      A list of build messages (in the format of dict).
    """
    messages = []
    for v in self.buildMessageTable.values():
      if (v['build_id'] == build_id and
          (message_type is None or v['message_type'] == message_type) and
          (message_subtype is None or
           v['message_subtype'] == message_subtype)):
        messages.append(v)

    return messages

  def StartBuildStage(self, build_stage_id):
    if build_stage_id > len(self.buildStageTable):
      return

    self.buildStageTable[build_stage_id]['status'] = (
        constants.BUILDER_STATUS_INFLIGHT)

  def WaitBuildStage(self, build_stage_id):
    if build_stage_id > len(self.buildStageTable):
      return

    self.buildStageTable[build_stage_id]['status'] = (
        constants.BUILDER_STATUS_WAITING)

  def ExtendDeadline(self, build_id, timeout):
    # No sanity checking in fake object.
    now = datetime.datetime.now()
    timediff = datetime.timedelta(seconds=timeout)
    self.buildStageTable[build_id]['deadline'] = now + timediff

  def FinishBuildStage(self, build_stage_id, status):
    if build_stage_id > len(self.buildStageTable):
      return

    self.buildStageTable[build_stage_id]['status'] = status

  def GetBuildStatus(self, build_id):
    """Gets the status of the build."""
    try:
      return self._TrimStatus(self.buildTable[build_id])
    except IndexError:
      return None

  def GetBuildStatuses(self, build_ids):
    """Gets the status of the builds."""
    return [self.GetBuildStatus(x) for x in build_ids]

  def GetSlaveStatuses(self, master_build_id, buildbucket_ids=None):
    """Gets the slaves of given build."""
    if buildbucket_ids is None:
      return [self._TrimStatus(b) for b in self.buildTable
              if b['master_build_id'] == master_build_id]
    else:
      return [self._TrimStatus(b) for b in self.buildTable
              if b['master_build_id'] == master_build_id and
              b['buildbucket_id'] in buildbucket_ids]

  def GetBuildsStages(self, build_ids):
    """Quick implementation of fake GetBuildsStages."""
    build_stages = []
    build_statuses = {b['id']: b for b in self.buildTable
                      if b['id'] in build_ids}
    for _id in self.buildStageTable:
      build_id = self.buildStageTable[_id]['build_id']
      if build_id in build_ids:
        stage = self.buildStageTable[_id].copy()
        stage['build_config'] = build_statuses[build_id]['build_config']
        build_stages.append(stage)

    return build_stages

  def GetBuildsStagesWithBuildbucketIds(self, buildbucket_ids):
    """Quick implementation of fake GetBuildsStagesWithBuildbucketIds."""
    build_stages = []
    build_statuses = {b['id']: b for b in self.buildTable
                      if b['buildbucket_id'] in buildbucket_ids}
    for _id in self.buildStageTable:
      build_id = self.buildStageTable[_id]['build_id']
      if build_id in build_statuses:
        stage = self.buildStageTable[_id].copy()
        stage['build_config'] = build_statuses[build_id]['build_config']
        build_stages.append(stage)

    return build_stages

  # pylint: disable=unused-argument
  def GetBuildHistory(self, build_config, num_results,
                      ignore_build_id=None, start_date=None, end_date=None,
                      branch=None, milestone_version=None,
                      platform_version=None, starting_build_id=None,
                      ending_build_id=None, final=False, reverse=False):
    """Returns the build history for the given |build_config|."""
    return self.GetBuildsHistory(
        build_configs=[build_config], num_results=num_results,
        ignore_build_id=ignore_build_id, start_date=start_date,
        end_date=end_date, milestone_version=milestone_version,
        platform_version=platform_version, starting_build_id=starting_build_id,
        final=final, reverse=reverse)

  def GetBuildsHistory(self, build_configs, num_results,
                       ignore_build_id=None, start_date=None, end_date=None,
                       milestone_version=None,
                       platform_version=None, starting_build_id=None,
                       final=False, reverse=False):
    """Returns the build history for the given |build_configs|."""
    builds = sorted(self.buildTable, reverse=(not reverse),
                    key=lambda x: x['id'])

    # Filter results.
    if build_configs:
      builds = [b for b in builds if b['build_config'] in build_configs]
    if ignore_build_id is not None:
      builds = [b for b in builds if b['buildbucket_id'] != ignore_build_id]
    if start_date is not None:
      builds = [b for b in builds
                if b['start_time'].date() >= start_date]
    if end_date is not None:
      builds = [b for b in builds
                if 'finish_time' in b and
                b['finish_time'] and
                b['finish_time'].date() <= end_date]
    if milestone_version is not None:
      builds = [b for b in builds
                if b.get('milestone_version') == milestone_version]
    if platform_version is not None:
      builds = [b for b in builds
                if b.get('platform_version') == platform_version]
    if starting_build_id is not None:
      builds = [b for b in builds if b['id'] >= starting_build_id]
    if final:
      builds = [b for b in builds
                if b.get('final') is True]

    if num_results != -1:
      return builds[:num_results]
    else:
      return builds

  def GetTimeToDeadline(self, build_id):
    """Gets the time remaining until deadline."""
    now = datetime.datetime.now()
    deadline = self.buildTable[build_id]['deadline']
    return max(0, (deadline - now).total_seconds())

  def GetKeyVals(self):
    """Gets contents of keyvalTable."""
    return self.fake_keyvals

  def GetBuildStatusesWithBuildbucketIds(self, buildbucket_ids):
    rows = []
    for row in self.buildTable:
      if (row['buildbucket_id'] in buildbucket_ids or
          str(row['buildbucket_id']) in buildbucket_ids):
        rows.append(self._TrimStatus(row))

    return rows

  def GetBuildsFailures(self, build_ids):
    """Gets the failure entries for all listed build_ids.

    Args:
      build_ids: list of build ids of the builds to fetch failures for.

    Returns:
      A list of failure_message_lib.StageFailure instances.
    """
    stage_failures = []
    for build_id in build_ids:
      b_dict = self.buildTable[build_id]
      bs_table = {k: v for k, v in self.buildStageTable.items()
                  if v['build_id'] == build_id}

      for f_dict in self.failureTable.values():
        if f_dict['build_stage_id'] in bs_table:
          bs_dict = bs_table[f_dict['build_stage_id']]
          stage_failures.append(
              failure_message_lib.StageFailure.GetStageFailureFromDicts(
                  f_dict, bs_dict, b_dict))

    return stage_failures

  def GetBuildRequestsForBuildConfigs(self, request_build_configs,
                                      num_results=-1, start_time=None):
    """Get BuildRequests for a list build_configs.

    Args:
      request_build_configs: build configs (string) to request.
      num_results: number of results to return, default to -1.
      start_time: get build requests sent after start_time.

    Returns:
      A list of BuildRequest instances sorted by id in descending order.
    """
    results = []
    for value in self.buildRequestTable.values():

      if start_time is not None and value['timestamp'] < start_time:
        continue

      if value['request_build_config'] in request_build_configs:
        results.append(build_requests.BuildRequest(
            value['id'], value['build_id'], value['request_build_config'],
            value['request_build_args'], value['request_buildbucket_id'],
            value['request_reason'], value['timestamp']))

    requests = sorted(results, key=lambda r: r.id, reverse=True)

    if num_results != -1:
      return requests[:num_results]
    else:
      return requests

  def GetLatestBuildRequestsForReason(self, request_reason,
                                      status=None,
                                      num_results=NUM_RESULTS_NO_LIMIT,
                                      n_days_back=7):
    """Gets the latest build_requests associated with the request_reason.

    Args:
      request_reason: The reason to filter by
      status: Whether to filter on status
      num_results: Number of results to return, default to
        self.NUM_RESULTS_NO_LIMIT.
      n_days_back: How many days back to look for build requests.

    Returns:
      A list of build_request.BuildRequest instances.
    """
    def _MatchesStatus(value):
      return status is None or value['status'] == status

    def _MatchesTimeConstraint(value):
      if n_days_back is None:
        return True

      # MySQL doesn't support timestamps with microsecond resolution
      now = datetime.datetime.now().replace(microsecond=0)
      then = now - datetime.timedelta(days=n_days_back)
      return then < value['timestamp']

    by_build_config = {}
    for value in self.buildRequestTable.values():
      if (value['request_reason'] == request_reason
          and _MatchesStatus(value)
          and _MatchesTimeConstraint(value)):
        by_build_config.setdefault(
            value['request_build_config'], []).append(value)

    max_in_group = [
        build_requests.BuildRequest(
            **max(group, key=lambda value: value['timestamp']))
        for group in by_build_config.values()]

    limit = None
    if num_results != self.NUM_RESULTS_NO_LIMIT:
      limit = num_results
    return max_in_group[:limit]

  def GetBuildRequestsForRequesterBuild(self, requester_build_id,
                                        request_reason=None):
    """Get the build_requests associated to the requester build.

    Args:
      requester_build_id: The build id of the requester build.
      request_reason: If provided, only return the build_request of the given
        request reason. Default to None.

    Returns:
      A list of build_request.BuildRequest instances.
    """
    results = []
    for value in self.buildRequestTable.values():
      if (value['build_id'] == requester_build_id and
          request_reason is None or request_reason == value['request_reason']):
        results.append(build_requests.BuildRequest(
            value['id'], value['build_id'], value['request_build_config'],
            value['request_build_args'], value['request_buildbucket_id'],
            value['request_reason'], value['timestamp']))

    return results

  def GetPreCQFlakeCounts(self, start_date=None, end_date=None):
    """Queries pre-CQ config flake & run counts.

    Args:
      start_date: The start date for the time window.
      end_date: The last day to include in the time window.

    Returns:
      A list of (config, flake, runs) tuples.
    """
    if start_date is None:
      start_date = datetime.datetime.now() - datetime.timedelta(days=7)

    def TimeConstraint(build):
      if end_date is not None and build['start_time'] >= end_date:
        return False
      return start_date <= build['start_time']

    def JoinWithBuild(actions):
      for action in actions:
        yield action, builds_by_id[action['build_id']]

    runs_by_build_config = {}
    builds_by_id = {}
    for build in self.buildTable:
      if TimeConstraint(build):
        runs_by_build_config.setdefault(build['build_config'], []).append(build)
        builds_by_id.setdefault(build['id'], []).append(build)

    actions_by_cl = {}
    for action in self.clActionTable:
      k = (action['change_number'],
           action['patch_number'],
           action['change_source'])
      actions_by_cl.setdefault(k, []).append(action)
    flakes = {}
    ignored_flake_build_configs = set(['pre-cq-launcher'])
    for _cl, actions in actions_by_cl.items():
      has_precq_success = any(
          c2['action'] == 'pre_cq_fully_verified'
          for c2 in actions)
      if has_precq_success:
        # We must use a list here instead of a set, because we're counting
        # flakes. We want to count two failures of the same config as two
        # different instances of flake.
        pre_cq_failed_configs = list([
            b['build_config']
            for c, b in JoinWithBuild(actions)
            if c['action'] == 'pre_cq_failed'
            and b['build_config'] not in ignored_flake_build_configs])

        for config in pre_cq_failed_configs:
          flakes.setdefault(config, 0)
          flakes[config] += 1

    result = []
    for config in runs_by_build_config:
      result.append(
          (config, flakes.get(config, 0), len(runs_by_build_config[config])))
    return result

  def UpdateBoardPerBuildMetadata(self, build_id, board, board_metadata):
    """Update the given board-per-build metadata.

    This function is not being tested. A function stub to spare a
    unittest error.
    """
