# Copyright 2015 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.

"""Controller for the build_annotations app.

This controller sits between the django models for cidb tables and the views
that power the app.
Keep non-trivial logic to aggregate data / optimize db access here and test it.
"""

from __future__ import print_function

import collections

from django.db import models
from django.db.models import query

from build_annotations import models as ba_models

# We need to fake out some system modules before importing chromite modules.
from cq_stats import fake_system_modules  # pylint: disable=unused-import
from chromite.lib import clactions


class BuildRow(collections.MutableMapping):
  """A database "view" that collects all relevant stats about a build."""

  def __init__(self, build_entry, build_stage_entries,
               cl_action_entries, failure_entries, annotations,
               costly_annotations_qs):
    """Initialize a BuildRow.

    Do not use QuerySets as arguments. All query sets must have been evaluated
    before creating this object. All data manipulation within this object is
    pure python.

    All non-trivial computation on this object should be lazy: Defer it to
    property getters.
    """
    assert not isinstance(build_entry, query.QuerySet)
    assert not isinstance(build_stage_entries, query.QuerySet)
    assert not isinstance(cl_action_entries, query.QuerySet)
    assert not isinstance(failure_entries, query.QuerySet)

    self._data = {}

    self.build_entry = build_entry
    self._build_stage_entries = build_stage_entries
    self._cl_action_entries = cl_action_entries
    self._failure_entries = failure_entries

    # The readonly data is accessible from this object as dict entries.
    self['id'] = self.build_entry.id
    self['build_number'] = self.build_entry.build_number
    self['status'] = self.build_entry.status
    self['summary'] = self.build_entry.summary
    self['start_time'] = self.build_entry.start_time
    if (self.build_entry.finish_time is not None and
        self['start_time'] is not None):
      self['run_time'] = self.build_entry.finish_time - self['start_time']
    else:
      self['run_time'] = None
    if self['start_time'] is not None:
      self['weekday'] = (self['start_time'].date().weekday() != 6)
    else:
      self['weekday'] = None
    self['chromeos_version'] = self.build_entry.full_version
    self['chrome_version'] = self.build_entry.chrome_version
    self['waterfall'] = self.build_entry.waterfall
    self['builder_name'] = self.build_entry.builder_name

    failed_stages = [x.name for x in build_stage_entries if
                     x.status == x.FAIL]
    self['failed_stages'] = ', '.join(failed_stages)
    self['picked_up_count'] = self._CountCLActions(
        ba_models.ClActionTable.PICKED_UP)
    self['submitted_count'] = self._CountCLActions(
        ba_models.ClActionTable.SUBMITTED)
    self['kicked_out_count'] = self._CountCLActions(
        ba_models.ClActionTable.KICKED_OUT)
    self['annotation_summary'] = self._SummaryAnnotations(annotations)
    self._costly_annotations_qs = costly_annotations_qs

  def GetAnnotationsQS(self):
    """Return the queryset backing annotations.

    Executing this queryset is costly because there is no way to optimize the
    query execution.
    Since this is a related_set queryset, that was further filtered, each item
    in the queryset causes a db hit.
    """
    return self._costly_annotations_qs

  def __getitem__(self, *args, **kwargs):
    return self._data.__getitem__(*args, **kwargs)

  def __iter__(self, *args, **kwargs):
    return self._data.__iter__(*args, **kwargs)

  def __len__(self, *args, **kwargs):
    return self._data.__len__(*args, **kwargs)

  def __setitem__(self, *args, **kwargs):
    return self._data.__setitem__(*args, **kwargs)

  def __delitem__(self, *args, **kwargs):
    return self._data.__delitem__(*args, **kwargs)

  def _CountCLActions(self, cl_action):
    actions = [x for x in self._cl_action_entries if x.action == cl_action]
    return len(actions)

  def _SummaryAnnotations(self, annotations):
    if not annotations:
      return ''

    result = '%d annotations: ' % len(annotations)
    summaries = []
    for annotation in annotations:
      summary = annotation.failure_category
      failure_message = annotation.failure_message
      blame_url = annotation.blame_url
      if failure_message:
        summary += '(%s)' % failure_message[:30]
      elif blame_url:
        summary += '(%s)' % blame_url[:30]
      summaries.append(summary)

    result += '; '.join(summaries)
    return result


class BuildRowController(object):
  """The 'controller' class that collates stats for builds.

  More details here.
  Unit-test this class please.
  """

  DEFAULT_NUM_BUILDS = 100

  def __init__(self):
    self._latest_build_id = 0
    self._build_rows_map = {}


  def GetStructuredBuilds(self, latest_build_id=None,
                          num_builds=DEFAULT_NUM_BUILDS, extra_filter_q=None):
    """The primary method to obtain stats for builds

    Args:
      latest_build_id: build_id of the latest build to query.
      num_builds: Number of build to query.
      extra_filter_q: An optional Q object to filter builds. Use GetQ* methods
          provided in this class to form the filter.

    Returns:
      A list of BuildRow entries for the queried builds.
    """
    # If we're not given any latest_build_id, we fetch the latest builds
    if latest_build_id is not None:
      build_qs = ba_models.BuildTable.objects.filter(id__lte=latest_build_id)
    else:
      build_qs = ba_models.BuildTable.objects.all()

    if extra_filter_q is not None:
      build_qs = build_qs.filter(extra_filter_q)
    build_qs = build_qs.order_by('-id')
    build_qs = build_qs[:num_builds]

    # Critical for performance: Prefetch all the join relations we'll need.
    build_qs = build_qs.prefetch_related('buildstagetable_set')
    build_qs = build_qs.prefetch_related('clactiontable_set')
    build_qs = build_qs.prefetch_related(
        'buildstagetable_set__failuretable_set')
    build_qs = build_qs.prefetch_related('annotationstable_set')

    # Now hit the database.
    build_entries = [x for x in build_qs]

    self._build_rows_map = {}
    build_rows = []
    for build_entry in build_entries:
      build_stage_entries = [x for x in build_entry.buildstagetable_set.all()]
      cl_action_entries = [x for x in build_entry.clactiontable_set.all()]
      failure_entries = []
      for entry in build_stage_entries:
        failure_entries += [x for x in entry.failuretable_set.all()]
      # Filter in python, filter'ing the queryset changes the queryset, and we
      # end up hitting the database again.
      annotations = [a for a in build_entry.annotationstable_set.all() if
                     a.deleted == False]
      costly_annotations_qs = build_entry.annotationstable_set.filter(
          deleted=False)

      build_row = BuildRow(build_entry, build_stage_entries, cl_action_entries,
                           failure_entries, annotations, costly_annotations_qs)

      self._build_rows_map[build_entry.id] = build_row
      build_rows.append(build_row)

    if build_entries:
      self._latest_build_id = build_entries[0].id

    return build_rows

  def GetHandlingTimeHistogram(self, latest_build_id=None,
                               num_builds=DEFAULT_NUM_BUILDS,
                               extra_filter_q=None):
    """Get CL handling time histogram."""
    # If we're not given any latest_build_id, we fetch the latest builds
    if latest_build_id is not None:
      build_qs = ba_models.BuildTable.objects.filter(id__lte=latest_build_id)
    else:
      build_qs = ba_models.BuildTable.objects.all()

    if extra_filter_q is not None:
      build_qs = build_qs.filter(extra_filter_q)
    build_qs = build_qs.order_by('-id')
    build_qs = build_qs[:num_builds]

    # Hit the database.
    build_entries = list(build_qs)
    claction_qs = ba_models.ClActionTable.objects.select_related('build_id')
    claction_qs = claction_qs.filter(
        build_id__in=set(b.id for b in build_entries))
    # Hit the database.
    claction_entries = [c for c in claction_qs]

    claction_history = clactions.CLActionHistory(
        self._JoinBuildTableClActionTable(build_entries, claction_entries))
    # Convert times seconds -> minutes.
    return {k: v / 60.0
            for k, v in claction_history.GetPatchHandlingTimes().iteritems()}

  def _JoinBuildTableClActionTable(self, build_entries, claction_entries):
    """Perform the join operation in python.

    Args:
      build_entries: A list of buildTable entries.
      claction_entries: A list of claction_entries.

    Returns:
      A list fo claction.CLAction objects created by joining the list of builds
      and list of claction entries.
    """
    claction_entries_by_build_id = {}
    for entry in claction_entries:
      entries = claction_entries_by_build_id.setdefault(entry.build_id.id, [])
      entries.append(entry)

    claction_list = []
    for build_entry in build_entries:
      for claction_entry in claction_entries_by_build_id.get(build_entry.id,
                                                             []):
        claction_list.append(clactions.CLAction(
            id=claction_entry.id,
            build_id=build_entry.id,
            action=claction_entry.action,
            reason=claction_entry.reason,
            build_config=build_entry.build_config,
            change_number=claction_entry.change_number,
            patch_number=claction_entry.patch_number,
            change_source=claction_entry.change_source,
            timestamp=claction_entry.timestamp))

    return claction_list

  ############################################################################
  # GetQ* methods are intended to be used in nifty search expressions to search
  # for builds.
  @classmethod
  def GetQNoAnnotations(cls):
    """Return a Q for builds with no annotations yet."""
    return models.Q(annotationstable__isnull=True)

  @classmethod
  def GetQRestrictToBuildConfig(cls, build_config):
    """Return a Q for builds with the given build_config."""
    return models.Q(build_config=build_config)

  @property
  def num_builds(self):
    return len(self._build_rows_map)

  @property
  def latest_build_id(self):
    return self._latest_build_id
