# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""URL endpoint for the main page which lists recent anomalies."""

import datetime
import logging

from google.appengine.ext import ndb

from dashboard import email_template
from dashboard import request_handler
from dashboard import utils
from dashboard.models import anomaly

_ANOMALY_FETCH_LIMIT = 1000
_DEFAULT_DAYS_TO_SHOW = 7
_DEFAULT_CHANGES_TO_SHOW = 10
_DEFAULT_SHERIFF_NAME = 'Chromium Perf Sheriff'


class MainHandler(request_handler.RequestHandler):
  """Displays the main overview page."""

  def get(self):
    """Renders the UI for the main overview page.

    Request parameters:
      days: Number of days to show anomalies for (optional).
      sheriff: Sheriff to show anomalies for (optional)
      num_changes: The number of improvements/regressions to list.

    Outputs:
      A HTML page that shows recent regressions, improvements.
    """
    days = int(self.request.get('days', _DEFAULT_DAYS_TO_SHOW))
    num_changes = int(self.request.get('num_changes', _DEFAULT_CHANGES_TO_SHOW))
    sheriff_name = self.request.get('sheriff', _DEFAULT_SHERIFF_NAME)
    sheriff = ndb.Key('Sheriff', sheriff_name)

    anomalies = _GetRecentAnomalies(days, sheriff)

    top_improvements = _TopImprovements(anomalies, num_changes)
    top_regressions = _TopRegressions(anomalies, num_changes)
    tests = _GetKeyToTestDict(top_improvements + top_regressions)

    template_dict = {
        'num_days': days,
        'num_changes': num_changes,
        'sheriff_name': sheriff_name,
        'improvements': _AnomalyInfoDicts(top_improvements, tests),
        'regressions': _AnomalyInfoDicts(top_regressions, tests),
    }
    self.RenderHtml('main.html', template_dict)


def _GetRecentAnomalies(days, sheriff):
  """Fetches recent Anomalies from the datastore.

  Args:
    days: Number of days old of the oldest Anomalies to fetch.
    sheriff: The ndb.Key of the Sheriff to fetch Anomalies for.

  Returns:
    A list of Anomaly entities sorted from large to small relative change.
  """
  oldest_time = datetime.datetime.now() - datetime.timedelta(days=days)
  anomalies_query = anomaly.Anomaly.query(
      anomaly.Anomaly.timestamp > oldest_time,
      anomaly.Anomaly.sheriff == sheriff)
  anomalies = anomalies_query.fetch(limit=_ANOMALY_FETCH_LIMIT)
  anomalies.sort(key=lambda a: abs(a.percent_changed), reverse=True)
  # We only want to list alerts that aren't marked invalid or ignored.
  anomalies = [a for a in anomalies if a.bug_id is None or a.bug_id > 0]
  return anomalies


def _GetKeyToTestDict(anomalies):
  """Returns a map of Test keys to entities for the given anomalies."""
  test_keys = {a.test for a in anomalies}
  tests = utils.GetMulti(test_keys)
  return {t.key: t for t in tests}


def _GetColorClass(percent_changed):
  """Returns a CSS class name for the anomaly, based on percent changed."""
  if percent_changed > 50:
    return 'over-50'
  if percent_changed > 40:
    return 'over-40'
  if percent_changed > 30:
    return 'over-30'
  if percent_changed > 20:
    return 'over-20'
  if percent_changed > 10:
    return 'over-10'
  return 'under-10'


def _AnomalyInfoDicts(anomalies, tests):
  """Returns information info about the given anomalies.

  Args:
    anomalies: A list of anomalies.
    tests: A dictionary mapping Test keys to Test entities.

  Returns:
    A list of dictionaries with information about the given anomalies.
  """
  anomaly_list = []
  for anomaly_entity in anomalies:
    # TODO(qyearsley): Add test coverage. See catapult:#1346.
    test = tests.get(anomaly_entity.test)
    if not test:
      logging.warning('No Test entity for key: %s.', anomaly_entity.test)
      continue
    subtest_path = '/'.join(test.test_path.split('/')[3:])
    graph_link = email_template.GetGroupReportPageLink(anomaly_entity)
    anomaly_list.append({
        'key': anomaly_entity.key.urlsafe(),
        'bug_id': anomaly_entity.bug_id or '',
        'start_revision': anomaly_entity.start_revision,
        'end_revision': anomaly_entity.end_revision,
        'master': test.master_name,
        'bot': test.bot_name,
        'testsuite': test.suite_name,
        'test': subtest_path,
        'percent_changed': anomaly_entity.GetDisplayPercentChanged(),
        'color_class': _GetColorClass(abs(anomaly_entity.percent_changed)),
        'improvement': anomaly_entity.is_improvement,
        'dashboard_link': graph_link,
    })
  return anomaly_list


def _TopImprovements(recent_anomalies, num_to_show):
  """Fills in the given template dictionary with top improvements.

  Args:
    recent_anomalies: A list of Anomaly entities sorted from large to small.
    num_to_show: The number of improvements to return.

  Returns:
    A list of top improvement Anomaly entities, in decreasing order.
  """
  improvements = [a for a in recent_anomalies if a.is_improvement]
  return improvements[:num_to_show]


def _TopRegressions(recent_anomalies, num_to_show):
  """Fills in the given template dictionary with top regressions.

  Args:
    recent_anomalies: A list of Anomaly entities sorted from large to small.
    num_to_show: The number of regressions to return.

  Returns:
    A list of top regression Anomaly entities, in decreasing order.
  """
  regressions = [a for a in recent_anomalies if not a.is_improvement]
  return regressions[:num_to_show]
