# Copyright 2018 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 or at
# https://developers.google.com/open-source/licenses/bsd

"""ts_mon JavaScript proxy handler."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

from framework import authdata
from framework import sql
from framework import xsrf

from gae_ts_mon.handlers import TSMonJSHandler
from gae_ts_mon.flask_handlers import TSMonJSFlaskHandler

from google.appengine.api import users

from infra_libs import ts_mon

import flask

STANDARD_FIELDS = [
  ts_mon.StringField('client_id'),
  ts_mon.StringField('host_name'),
  ts_mon.BooleanField('document_visible'),
]


# User action metrics.
ISSUE_CREATE_LATENCY_METRIC = ts_mon.CumulativeDistributionMetric(
  'monorail/frontend/issue_create_latency', (
    'Latency between Issue Entry form submission and page load of '
    'the subsequent issue page.'
  ), field_spec=STANDARD_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)
ISSUE_UPDATE_LATENCY_METRIC = ts_mon.CumulativeDistributionMetric(
  'monorail/frontend/issue_update_latency', (
    'Latency between Issue Update form submission and page load of '
    'the subsequent issue page.'
  ), field_spec=STANDARD_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)
AUTOCOMPLETE_POPULATE_LATENCY_METRIC = ts_mon.CumulativeDistributionMetric(
  'monorail/frontend/autocomplete_populate_latency', (
    'Latency between page load and autocomplete options loading.'
  ), field_spec=STANDARD_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)
CHARTS_SWITCH_DATE_RANGE_METRIC = ts_mon.CounterMetric(
  'monorail/frontend/charts/switch_date_range', (
    'Number of times user clicks frequency button.'
  ), field_spec=STANDARD_FIELDS + [ts_mon.IntegerField('date_range')])

# Page load metrics.
ISSUE_COMMENTS_LOAD_EXTRA_FIELDS = [
  ts_mon.StringField('template_name'),
  ts_mon.BooleanField('full_app_load'),
]
ISSUE_COMMENTS_LOAD_LATENCY_METRIC = ts_mon.CumulativeDistributionMetric(
  'monorail/frontend/issue_comments_load_latency', (
    'Time from navigation or click to issue comments loaded.'
  ), field_spec=STANDARD_FIELDS + ISSUE_COMMENTS_LOAD_EXTRA_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)
DOM_CONTENT_LOADED_EXTRA_FIELDS = [
  ts_mon.StringField('template_name')]
DOM_CONTENT_LOADED_METRIC = ts_mon.CumulativeDistributionMetric(
  'frontend/dom_content_loaded', (
    'domContentLoaded performance timing.'
  ), field_spec=STANDARD_FIELDS + DOM_CONTENT_LOADED_EXTRA_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)


ISSUE_LIST_LOAD_EXTRA_FIELDS = [
  ts_mon.StringField('template_name'),
  ts_mon.BooleanField('full_app_load'),
]
ISSUE_LIST_LOAD_LATENCY_METRIC = ts_mon.CumulativeDistributionMetric(
  'monorail/frontend/issue_list_load_latency', (
    'Time from navigation or click to search issues list loaded.'
  ), field_spec=STANDARD_FIELDS + ISSUE_LIST_LOAD_EXTRA_FIELDS,
  units=ts_mon.MetricsDataUnits.MILLISECONDS)


class MonorailTSMonJSHandler(TSMonJSHandler):

  def __init__(self, request=None, response=None):
    super(MonorailTSMonJSHandler, self).__init__(request, response)
    self.register_metrics([
        ISSUE_CREATE_LATENCY_METRIC,
        ISSUE_UPDATE_LATENCY_METRIC,
        AUTOCOMPLETE_POPULATE_LATENCY_METRIC,
        CHARTS_SWITCH_DATE_RANGE_METRIC,
        ISSUE_COMMENTS_LOAD_LATENCY_METRIC,
        DOM_CONTENT_LOADED_METRIC,
        ISSUE_LIST_LOAD_LATENCY_METRIC])

  def xsrf_is_valid(self, body):
    """This method expects the body dictionary to include two fields:
    `token` and `user_id`.
    """
    cnxn = sql.MonorailConnection()
    token = body.get('token')
    user = users.get_current_user()
    email = user.email() if user else None

    services = self.app.config.get('services')
    auth = authdata.AuthData.FromEmail(cnxn, email, services, autocreate=False)
    try:
      xsrf.ValidateToken(token, auth.user_id, xsrf.XHR_SERVLET_PATH)
      return True
    except xsrf.TokenIncorrect:
      return False


class FlaskMonorailTSMonJSHandler(TSMonJSFlaskHandler):

  def __init__(self, services=None):
    super(FlaskMonorailTSMonJSHandler, self).__init__(
        flask=flask, services=services)
    self.register_metrics(
        [
            ISSUE_CREATE_LATENCY_METRIC, ISSUE_UPDATE_LATENCY_METRIC,
            AUTOCOMPLETE_POPULATE_LATENCY_METRIC,
            CHARTS_SWITCH_DATE_RANGE_METRIC, ISSUE_COMMENTS_LOAD_LATENCY_METRIC,
            DOM_CONTENT_LOADED_METRIC, ISSUE_LIST_LOAD_LATENCY_METRIC
        ])

  def xsrf_is_valid(self, body):
    """This method expects the body dictionary to include two fields:
    `token` and `user_id`.
    """
    cnxn = sql.MonorailConnection()
    token = body.get('token')
    user = users.get_current_user()
    email = user.email() if user else None

    services = self.service
    auth = authdata.AuthData.FromEmail(cnxn, email, services, autocreate=False)
    try:
      xsrf.ValidateToken(token, auth.user_id, xsrf.XHR_SERVLET_PATH)
      return True
    except xsrf.TokenIncorrect:
      return False

  def PostMonorailTSMonJSHandler(self):
    return self.post()
