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

"""Provides the web interface for changing internal_only property of a Bot."""

import logging

from google.appengine.api import taskqueue
from google.appengine.datastore import datastore_query
from google.appengine.ext import ndb

from dashboard import datastore_hooks
from dashboard import request_handler
from dashboard.models import anomaly
from dashboard.models import graph_data

# Number of Row entities to process at once.
_MAX_ROWS_TO_PUT = 25

# Number of Test entities to process at once.
_MAX_TESTS_TO_PUT = 25

# Which queue to use for tasks started by this handler. Must be in queue.yaml.
_QUEUE_NAME = 'migrate-queue'


class ChangeInternalOnlyHandler(request_handler.RequestHandler):
  """Changes internal_only property of Bot, Test, and Row."""

  def get(self):
    """Renders the UI for selecting bots."""
    masters = {}
    bots = graph_data.Bot.query().fetch()
    for bot in bots:
      master_name = bot.key.parent().string_id()
      bot_name = bot.key.string_id()
      bots = masters.setdefault(master_name, [])
      bots.append({
          'name': bot_name,
          'internal_only': bot.internal_only,
      })
    logging.info('MASTERS: %s', masters)

    self.RenderHtml('change_internal_only.html', {
        'masters': masters,
    })

  def post(self):
    """Updates the selected bots internal_only property.

    POST requests will be made by the task queue; tasks are added to the task
    queue either by a kick-off POST from the front-end form, or by this handler
    itself.

    Request parameters:
      internal_only: "true" if turning on internal_only, else "false".
      bots: Bots to update. Multiple bots parameters are possible; the value
          of each should be a string like "MasterName/platform-name".
      test: An urlsafe Key for a Test entity.
      cursor: An urlsafe Cursor; this parameter is only given if we're part-way
          through processing a Bot or a Test.

    Outputs:
      A message to the user if this request was started by the web form,
      or an error message if something went wrong, or nothing.
    """
    # /change_internal_only should be only accessible if one has administrator
    # privileges, so requests are guaranteed to be authorized.
    datastore_hooks.SetPrivilegedRequest()

    internal_only_string = self.request.get('internal_only')
    if internal_only_string == 'true':
      internal_only = True
    elif internal_only_string == 'false':
      internal_only = False
    else:
      self.ReportError('No internal_only field')
      return

    bot_names = self.request.get_all('bots')
    test_key_urlsafe = self.request.get('test')
    cursor = self.request.get('cursor', None)

    if bot_names and len(bot_names) > 1:
      self._UpdateMultipleBots(bot_names, internal_only)
      self.RenderHtml('result.html', {
          'headline': ('Updating internal_only. This may take some time '
                       'depending on the data to update. Check the task queue '
                       'to determine whether the job is still in progress.'),
      })
    elif bot_names and len(bot_names) == 1:
      self._UpdateBot(bot_names[0], internal_only, cursor=cursor)
    elif test_key_urlsafe:
      self._UpdateTest(test_key_urlsafe, internal_only, cursor=cursor)

  def _UpdateMultipleBots(self, bot_names, internal_only):
    """Kicks off update tasks for individual bots and their tests."""
    for bot_name in bot_names:
      taskqueue.add(
          url='/change_internal_only',
          params={
              'bots': bot_name,
              'internal_only': 'true' if internal_only else 'false'
          },
          queue_name=_QUEUE_NAME)

  def _UpdateBot(self, bot_name, internal_only, cursor=None):
    """Starts updating internal_only for the given bot and associated data."""
    master, bot = bot_name.split('/')
    bot_key = ndb.Key('Master', master, 'Bot', bot)

    if not cursor:
      # First time updating for this Bot.
      bot_entity = bot_key.get()
      if bot_entity.internal_only != internal_only:
        bot_entity.internal_only = internal_only
        bot_entity.put()
    else:
      cursor = datastore_query.Cursor(urlsafe=cursor)

    # Fetch a certain number of Test entities starting from cursor. See:
    # https://developers.google.com/appengine/docs/python/ndb/queryclass

    # Start update tasks for each existing subordinate Test.
    test_query = graph_data.Test.query(ancestor=bot_key)
    test_keys, next_cursor, more = test_query.fetch_page(
        _MAX_TESTS_TO_PUT, start_cursor=cursor, keys_only=True)

    for test_key in test_keys:
      taskqueue.add(
          url='/change_internal_only',
          params={
              'test': test_key.urlsafe(),
              'internal_only': 'true' if internal_only else 'false',
          },
          queue_name=_QUEUE_NAME)

    if more:
      taskqueue.add(
          url='/change_internal_only',
          params={
              'bots': bot_name,
              'cursor': next_cursor.urlsafe(),
              'internal_only': 'true' if internal_only else 'false',
          },
          queue_name=_QUEUE_NAME)

  def _UpdateTest(self, test_key_urlsafe, internal_only, cursor=None):
    """Updates the given Test and associated Row entities."""
    test_key = ndb.Key(urlsafe=test_key_urlsafe)
    if not cursor:
      # First time updating for this Test.
      test_entity = test_key.get()
      if test_entity.internal_only != internal_only:
        test_entity.internal_only = internal_only
        test_entity.put()

      # Update all of the Anomaly entities for this test.
      # Assuming that this should be fast enough to do in one request
      # for any one test.
      query = anomaly.Anomaly.query(anomaly.Anomaly.test == test_key)
      anomalies = query.fetch()
      for anomaly_entity in anomalies:
        if anomaly_entity.internal_only != internal_only:
          anomaly_entity.internal_only = internal_only
      ndb.put_multi(anomalies)
    else:
      cursor = datastore_query.Cursor(urlsafe=cursor)

    # Fetch a certain number of Row entities starting from cursor.
    rows_query = graph_data.Row.query(graph_data.Row.parent_test == test_key)
    rows, next_cursor, more = rows_query.fetch_page(
        _MAX_ROWS_TO_PUT, start_cursor=cursor)

    for row in rows:
      if row.internal_only != internal_only:
        row.internal_only = internal_only
    ndb.put_multi(rows)

    if more:
      taskqueue.add(
          url='/change_internal_only',
          params={
              'test': test_key_urlsafe,
              'cursor': next_cursor.urlsafe(),
              'internal_only': 'true' if internal_only else 'false',
          },
          queue_name=_QUEUE_NAME)
