# Copyright 2016 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 to allow bisect bots to post results to the dashboard."""

import json
import logging

from google.appengine.api import app_identity
from google.appengine.ext import ndb

from dashboard import datastore_hooks
from dashboard import post_data_handler
from dashboard import update_bug_with_results
from dashboard import utils
from dashboard.models import try_job

_EXPECTED_RESULT_PROPERTIES = {
    'status': ['pending', 'started', 'completed', 'failed', 'aborted'],
}


class BadRequestError(Exception):
  """An error indicating that a 400 response status should be returned."""
  pass


class PostBisectResultsHandler(post_data_handler.PostDataHandler):

  def post(self):
    """Validates data parameter and saves to TryJob entity.

    Bisect results come from a "data" parameter, which is a JSON encoding of a
    dictionary.

    The required fields are "master", "bot", "test".

    Request parameters:
      data: JSON encoding of a dictionary.

    Outputs:
      Empty 200 response with if successful,
      200 response with warning message if optional data is invalid,
      403 response with error message if sender IP is not white-listed,
      400 response with error message if required data is invalid.
      500 with error message otherwise.
    """
    datastore_hooks.SetPrivilegedRequest()
    if not self._CheckIpAgainstWhitelist():
      return

    data = self.request.get('data')
    if not data:
      self.ReportError('Missing "data" parameter.', status=400)
      return

    try:
      data = json.loads(self.request.get('data'))
    except ValueError:
      self.ReportError('Invalid JSON string.', status=400)
      return

    logging.info('Received data: %s', data)

    try:
      _ValidateResultsData(data)
      job = _GetTryJob(data)
      if not job:
        self.ReportWarning('No try job found.')
        return
      _UpdateTryJob(job, data)
      update_bug_with_results.UpdateQuickLog(job)
    except BadRequestError as error:
      self.ReportError(error.message, status=400)


def _ValidateResultsData(results_data):
  utils.Validate(_EXPECTED_RESULT_PROPERTIES, results_data)
  # TODO(chrisphan): Validate other values.


def _UpdateTryJob(job, results_data):
  if not job.results_data:
    job.results_data = {}
  job.results_data.update(results_data)
  job.results_data['issue_url'] = (job.results_data.get('issue_url') or
                                   _IssueURL(job))
  job.put()


def _GetTryJob(results_data):
  try_job_id = results_data.get('try_job_id')
  if not try_job_id:
    return None
  job = ndb.Key(try_job.TryJob, try_job_id).get()
  return job


def _IssueURL(job):
  """Returns a URL for information about a bisect try job."""
  hostname = app_identity.get_default_version_hostname()
  job_id = job.buildbucket_job_id
  return 'https://%s/buildbucket_job_status/%s' % (hostname, job_id)
