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

"""Routes for inspecting CL-exonerator's state and debugging it."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import httplib
import itertools

from chromite.lib import cidb
from chromite.lib import clactions
from chromite.lib import parallel
import flask
import flask_httpauth
import jsonschema
from werkzeug import security

import config
from exonerator import cidblib
from exonerator import gerrit_cq
from exonerator import innocent_cls_cq


app = flask.Blueprint('debug_routes', __name__)
auth = flask_httpauth.HTTPBasicAuth()
config = config.Config()
_EXONERATE_SCHEMA = {
    'type': 'object',
    'properties': {
        'cl': {'type': 'number'},
        'patch': {'type': 'number'},
        'build_id': {'type': 'number'},
        'internal': {'type': 'boolean'},
    },
    'required': ['cl', 'patch', 'build_id', 'internal']
}


@auth.verify_password
def VerifyPassword(username, password):
  """Checks if a username / password is valid.

  Args:
    username: The username to check.
    password: The given password.
  """
  # Unknown user, or the password was not set.
  if username not in config.users or config.users[username] is None:
    # Note: shortcircuiting here allows attackers to find out which usernames
    # are valid by measuring timings; in this case, that's irrelevant since the
    # set of users is public.
    return False
  return security.check_password_hash(config.users[username], password)


@app.route('/exonerate', methods=['POST'])
@auth.login_required
def Exonerate():
  """Exonerates a given cl"""
  body = flask.request.get_json(force=True)
  _ValidateSchema(_EXONERATE_SCHEMA, body)

  change = clactions.GerritPatchTuple(
      body['cl'], body['patch'], body['internal'])

  conn = cidb.CIDBConnection(
      config.cidb_cred_dir, for_service=config.is_service)
  exonerated = gerrit_cq.MaybeExonerate(change, body['build_id'])
  if exonerated:
    cidblib.InsertExoneratedCLActions(conn, [change], 'cq')
  return flask.jsonify({'exonerated': exonerated})


def _ValidateSchema(schema, data):
  """Validates that |data| follows a JSON |schema|, aborting if not."""
  try:
    jsonschema.validate(data, schema)
  except jsonschema.ValidationError:
    flask.abort(httplib.BAD_REQUEST)


@app.route('/cls')
@auth.login_required
def CLs():
  """A route for inspecting CLs to be examined by exonerator."""
  valid_cl_types = {
      'pending': PendingCLs,
      'ready': ReadyCLs,
  }
  cl_type = flask.request.args.get('type')
  if cl_type not in valid_cl_types:
    flask.abort(httplib.BAD_REQUEST)

  conn = cidb.CIDBConnection(
      config.cidb_cred_dir, for_service=config.is_service)
  innocent_batches = innocent_cls_cq.NewInnocentCLs(conn, checkpoint=False)
  innocents = itertools.chain.from_iterable(innocent_batches)

  if 'limit' in flask.request.args:
    limit = flask.request.args.get('limit', type=int)
    innocents = itertools.islice(innocents, limit)

  return flask.jsonify(cls=valid_cl_types[cl_type](innocents))


def PendingCLs(innocents):
  """Pending innocent CLs.

  Args:
    innocents: A sequence of innocent GerritPatchTuples

  Returns:
    The list of patches converted to human-readable strings.
  """
  return [str(c) for c, _ in innocents]


def ReadyCLs(innocents):
  """Filters pending CLs which can be exonerated.

  See `exonerator.gerrit.CanBeMarkedReady`.

  Args:
    innocents: A sequence of innocent GerritPatchTuples

  Returns:
    The list of patches which are ready, converted to human-readable strings.
  """
  changes = [c for c, _ in innocents]

  ready_states = parallel.RunTasksInProcessPool(
      gerrit_cq.CanBeMarkedReady,
      [[c] for c in changes])

  return [
      str(c)
      for c, ready in zip(changes, ready_states)
      if ready
  ]
