# 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 CL exonerator."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import httplib
import sys

from chromite.lib import cidb
from chromite.lib import parallel
from chromite.lib import cros_logging as logging
import flask

import config
import debug_routes
import flex_ts_mon.setup
from exonerator import cidblib
from exonerator import gerrit_cq
from exonerator import gerrit_precq
from exonerator import innocent_cls_cq
from exonerator import innocent_cls_precq
from exonerator import weekend


app = flask.Flask(__name__)
app.register_blueprint(debug_routes.app)
config = config.Config()

# TODO(phobbs) make this higher at night / weekend
_CQ_BUILD_LIMIT = 1

APPENGINE_CRON_HEADER = 'X-Appengine-Cron'
PRE_CQ_TYPE = 'pre-cq'
CQ_TYPE = 'cq'

# This must be done at the top level because gunicorn and nginx does not run us
# as __main__
logging.basicConfig(level=logging.DEBUG)


@app.route('/')
def Hello():
  """Placeholder route"""
  return 'hello world'


# Ideally this would be a POST, but Appengine cron only makes GET requests.
@app.route('/cron/exonerate/cq')
def ExonerateCQ():
  """Exonerates innocent CLs which were kicked out."""
  if not _RequestIsFromAppEngineCron():
    flask.abort(httplib.UNAUTHORIZED)

  conn = cidb.CIDBConnection(
      config.cidb_cred_dir, for_service=config.is_service)
  all_exonerated = []
  for batch in innocent_cls_cq.NewInnocentCLs(conn, limit=_CQ_BUILD_LIMIT):
    all_exonerated.extend(_ExonerateBatch(conn, batch, CQ_TYPE))

  return flask.jsonify(exonerated=all_exonerated)


@app.route('/cron/exonerate/pre-cq')
def ExoneratePreCQ():
  """Exonerates innocent CLs which were kicked out."""
  if not _RequestIsFromAppEngineCron():
    flask.abort(httplib.UNAUTHORIZED)

  # Blunt force disable for PreCQ exonerator
  return

  conn = cidb.CIDBConnection(
      config.cidb_cred_dir, for_service=config.is_service)
  all_exonerated = []
  on_peak = not weekend.HaveUnlimitedResources()
  for batch in innocent_cls_precq.NewInnocentCLs(conn, on_peak=on_peak):
    all_exonerated.extend(_ExonerateBatch(conn, batch, PRE_CQ_TYPE))

  return flask.jsonify(exonerated=all_exonerated)


def _ExonerateBatch(conn, batch, exoneration_type):
  """Exonerates a batch of changes, then inserts CLActions.

  Args:
    conn: The CIDBConnection to use
    batch: A List[exonerator.gerrit_cq.ChangeWithBuild] of changes to exonerate.
    exoneration_type: A string in ('cq', 'pre-cq')
  """
  exonerate_f = {
      'cq': gerrit_cq.MaybeExonerate,
      'pre-cq': gerrit_precq.MaybeExonerate,
  }[exoneration_type]
  exonerated_flags = parallel.RunTasksInProcessPool(
      exonerate_f,
      [[change, build_id] for change, build_id in batch])

  exonerated_changes = []
  for change, exonerated in zip(batch, exonerated_flags):
    if exonerated:
      exonerated_changes.append(change)

  if exonerated_changes:
    cidblib.InsertExoneratedCLActions(
        conn, exonerated_changes, exoneration_type)

  return exonerated_changes


def _RequestIsFromAppEngineCron():
  """Returns whether the request came from Appengine's cron service.

  See https://cloud.google.com/appengine/docs/flexible/python/
      scheduling-jobs-with-cron-yaml#validating_cron_requests
  for more details.
  """
  return flask.request.headers.get(APPENGINE_CRON_HEADER) == 'true'


_METRICS_DEBUG_FILE = '/tmp/metrics-debug.log' if config.debug else None


@app.before_first_request
def SetupWorkerMetrics():
  """Sets up the metrics sending thread.

  This must happen post-fork, or else the gunicorn workers will all use the
  same hostname and task_num arguments, causing conflicts when they flush
  metrics.
  """
  flex_ts_mon.setup.SetupTsMonGlobalState(debug_file=_METRICS_DEBUG_FILE)


if __name__ == '__main__':
  print('Run the app locally with '
        '"gunicorn -c gunicorn.conf.py -b :8080 main:app"', file=sys.stderr)
