# 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


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_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

    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)

    # Annotations are treated specially. They are not availabe via the dict API.
    self.annotations = annotations_qs
    self['annotation_summary'] = self._SummaryAnnotations()

  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):
    if not self.annotations:
      return ''

    result = '%d annotations: ' % len(self.annotations)
    summaries = []
    for annotation in self.annotations:
      summary = annotation.failure_category
      failure_message = annotation.failure_message
      if failure_message is not None:
        summary += '(%s)' % failure_message[: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()]
      annotations_qs = build_entry.annotationstable_set.all()

      build_row = BuildRow(build_entry, build_stage_entries, cl_action_entries,
                           failure_entries, 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

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

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

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