# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Helper methods for unittests."""

from typing import Generator, Iterable, List, Optional, Set, Tuple, Type

# vpython-provided modules.
import pandas  # pylint: disable=import-error

# //testing imports.
from unexpected_passes_common import builders
from unexpected_passes_common import expectations
from unexpected_passes_common import data_types
from unexpected_passes_common import queries as queries_module


def CreateStatsWithPassFails(passes: int, fails: int) -> data_types.BuildStats:
  stats = data_types.BuildStats()
  for _ in range(passes):
    stats.AddPassedBuild(frozenset())
  for i in range(fails):
    stats.AddFailedBuild('build_id%d' % i, frozenset())
  return stats


# id_ is used instead of id since id is a python built-in.
def FakeQueryResult(
  builder_name: str,
  id_: str,
  test_id: str,
  status: str,
  typ_tags: Iterable[str],
  step_name: str,
) -> pandas.Series:
  return pandas.Series(
    data={
      'builder_name': builder_name,
      'id': id_,
      'test_id': test_id,
      'test_name': test_id.split('.')[-1],
      'status': status,
      'typ_tags': list(typ_tags),
      'step_name': step_name,
    }
  )


class SimpleBigQueryQuerier(queries_module.BigQueryQuerier):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.query_results = []

  def _GetSeriesForQuery(self, _) -> Generator[pandas.Series, None, None]:
    for r in self.query_results:
      yield r

  def _GetRelevantExpectationFilesForQueryResult(self, _) -> None:
    return None

  def _GetPublicCiQuery(self) -> str:
    return 'public_ci'

  def _GetInternalCiQuery(self) -> str:
    return 'internal_ci'

  def _GetPublicTryQuery(self) -> str:
    return 'public_try'

  def _GetInternalTryQuery(self) -> str:
    return 'internal_try'


def CreateGenericQuerier(
  suite: Optional[str] = None,
  project: Optional[str] = None,
  num_samples: Optional[int] = None,
  keep_unmatched_results: bool = False,
  cls: Optional[Type[queries_module.BigQueryQuerier]] = None,
) -> queries_module.BigQueryQuerier:
  suite = suite or 'pixel'
  project = project or 'project'
  num_samples = num_samples or 5
  cls = cls or SimpleBigQueryQuerier
  return cls(suite, project, num_samples, keep_unmatched_results)


def GetArgsForMockCall(
  call_args_list: List[tuple], call_number: int
) -> Tuple[tuple, dict]:
  """Helper to more sanely get call args from a mocked method.

  Args:
    call_args_list: The call_args_list member from the mock in question.
    call_number: The call number to pull args from, starting at 0 for the first
        call to the method.

  Returns:
    A tuple (args, kwargs). |args| is a list of arguments passed to the method.
    |kwargs| is a dict containing the keyword arguments padded to the method.
  """
  args = call_args_list[call_number][0]
  kwargs = call_args_list[call_number][1]
  return args, kwargs


class GenericBuilders(builders.Builders):
  # pylint: disable=useless-super-delegation
  def __init__(
    self, suite: Optional[str] = None, include_internal_builders: bool = False
  ):
    super().__init__(suite, include_internal_builders)

  # pylint: enable=useless-super-delegation

  def _BuilderRunsTestOfInterest(self, _test_map) -> bool:
    return True

  def GetIsolateNames(self) -> Set[str]:
    return set()

  def GetFakeCiBuilders(self) -> dict:
    return {}

  def GetNonChromiumBuilders(self) -> Set[data_types.BuilderEntry]:
    return set()


def RegisterGenericBuildersImplementation() -> None:
  builders.RegisterInstance(GenericBuilders())


class GenericExpectations(expectations.Expectations):
  def GetExpectationFilepaths(self) -> list:
    return []

  def _GetExpectationFileTagHeader(self, _) -> str:
    return """\
# tags: [ linux mac win ]
# tags: [ amd intel nvidia ]
# results: [ Failure RetryOnFailure Skip Pass ]
"""

  def _GetKnownTags(self) -> Set[str]:
    return set(['linux', 'mac', 'win', 'amd', 'intel', 'nvidia'])


def CreateGenericExpectations() -> GenericExpectations:
  return GenericExpectations()


def RegisterGenericExpectationsImplementation() -> None:
  expectations.RegisterInstance(CreateGenericExpectations())
