# Copyright 2013 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


import re
import sys

import json
import logging
import math

import perf_result_data_type


# Mapping from result type to test output
RESULT_TYPES = {perf_result_data_type.UNIMPORTANT: 'RESULT ',
                perf_result_data_type.DEFAULT: '*RESULT ',
                perf_result_data_type.INFORMATIONAL: '',
                perf_result_data_type.UNIMPORTANT_HISTOGRAM: 'HISTOGRAM ',
                perf_result_data_type.HISTOGRAM: '*HISTOGRAM '}


def _EscapePerfResult(s):
  """Escapes |s| for use in a perf result."""
  return re.sub('[\:|=/#&,]', '_', s)


def FlattenList(values):
  """Returns a simple list without sub-lists."""
  ret = []
  for entry in values:
    if isinstance(entry, list):
      ret.extend(FlattenList(entry))
    else:
      ret.append(entry)
  return ret


def GeomMeanAndStdDevFromHistogram(histogram_json):
  histogram = json.loads(histogram_json)
  # Handle empty histograms gracefully.
  if not 'buckets' in histogram:
    return 0.0, 0.0
  count = 0
  sum_of_logs = 0
  for bucket in histogram['buckets']:
    if 'high' in bucket:
      bucket['mean'] = (bucket['low'] + bucket['high']) / 2.0
    else:
      bucket['mean'] = bucket['low']
    if bucket['mean'] > 0:
      sum_of_logs += math.log(bucket['mean']) * bucket['count']
      count += bucket['count']

  if count == 0:
    return 0.0, 0.0

  sum_of_squares = 0
  geom_mean = math.exp(sum_of_logs / count)
  for bucket in histogram['buckets']:
    if bucket['mean'] > 0:
      sum_of_squares += (bucket['mean'] - geom_mean) ** 2 * bucket['count']
  return geom_mean, math.sqrt(sum_of_squares / count)


def _ValueToString(v):
  # Special case for floats so we don't print using scientific notation.
  if isinstance(v, float):
    return '%f' % v
  else:
    return str(v)


def _MeanAndStdDevFromList(values):
  avg = None
  sd = None
  if len(values) > 1:
    try:
      value = '[%s]' % ','.join([_ValueToString(v) for v in values])
      avg = sum([float(v) for v in values]) / len(values)
      sqdiffs = [(float(v) - avg) ** 2 for v in values]
      variance = sum(sqdiffs) / (len(values) - 1)
      sd = math.sqrt(variance)
    except ValueError:
      value = ', '.join(values)
  else:
    value = values[0]
  return value, avg, sd


def PrintPages(page_list):
  """Prints list of pages to stdout in the format required by perf tests."""
  print('Pages: [%s]' % ','.join([_EscapePerfResult(p) for p in page_list]))


def PrintPerfResult(measurement, trace, values, units,
                    result_type=perf_result_data_type.DEFAULT,
                    print_to_stdout=True):
  """Prints numerical data to stdout in the format required by perf tests.

  The string args may be empty but they must not contain any colons (:) or
  equals signs (=).
  This is parsed by the buildbot using:
  http://src.chromium.org/viewvc/chrome/trunk/tools/build/scripts/slave/process_log_utils.py

  Args:
    measurement: A description of the quantity being measured, e.g. "vm_peak".
        On the dashboard, this maps to a particular graph. Mandatory.
    trace: A description of the particular data point, e.g. "reference".
        On the dashboard, this maps to a particular "line" in the graph.
        Mandatory.
    values: A list of numeric measured values. An N-dimensional list will be
        flattened and treated as a simple list.
    units: A description of the units of measure, e.g. "bytes".
    result_type: Accepts values of perf_result_data_type.ALL_TYPES.
    print_to_stdout: If True, prints the output in stdout instead of returning
        the output to caller.

    Returns:
      String of the formated perf result.
  """
  assert perf_result_data_type.IsValidType(result_type), \
         'result type: %s is invalid' % result_type

  trace_name = _EscapePerfResult(trace)

  if (result_type == perf_result_data_type.UNIMPORTANT or
      result_type == perf_result_data_type.DEFAULT or
      result_type == perf_result_data_type.INFORMATIONAL):
    assert isinstance(values, list)
    assert '/' not in measurement
    flattened_values = FlattenList(values)
    assert len(flattened_values)
    value, avg, sd = _MeanAndStdDevFromList(flattened_values)
    output = '%s%s: %s%s%s %s' % (
        RESULT_TYPES[result_type],
        _EscapePerfResult(measurement),
        trace_name,
        # Do not show equal sign if the trace is empty. Usually it happens when
        # measurement is enough clear to describe the result.
        '= ' if trace_name else '',
        value,
        units)
  else:
    assert perf_result_data_type.IsHistogram(result_type)
    assert isinstance(values, list)
    # The histograms can only be printed individually, there's no computation
    # across different histograms.
    assert len(values) == 1
    value = values[0]
    output = '%s%s: %s= %s %s' % (
        RESULT_TYPES[result_type],
        _EscapePerfResult(measurement),
        trace_name,
        value,
        units)
    avg, sd = GeomMeanAndStdDevFromHistogram(value)

  if avg:
    output += '\nAvg %s: %f%s' % (measurement, avg, units)
  if sd:
    output += '\nSd  %s: %f%s' % (measurement, sd, units)
  if print_to_stdout:
    print(output)
    sys.stdout.flush()
  return output


def ReportPerfResult(chart_data, graph_title, trace_title, value, units,
                     improvement_direction='down', important=True):
  """Outputs test results in correct format.

  If chart_data is None, it outputs data in old format. If chart_data is a
  dictionary, formats in chartjson format. If any other format defaults to
  old format.

  Args:
    chart_data: A dictionary corresponding to perf results in the chartjson
        format.
    graph_title: A string containing the name of the chart to add the result
        to.
    trace_title: A string containing the name of the trace within the chart
        to add the result to.
    value: The value of the result being reported.
    units: The units of the value being reported.
    improvement_direction: A string denoting whether higher or lower is
        better for the result. Either 'up' or 'down'.
    important: A boolean denoting whether the result is important or not.
  """
  if chart_data and isinstance(chart_data, dict):
    chart_data['charts'].setdefault(graph_title, {})
    chart_data['charts'][graph_title][trace_title] = {
        'type': 'scalar',
        'value': value,
        'units': units,
        'improvement_direction': improvement_direction,
        'important': important
    }
  else:
    PrintPerfResult(graph_title, trace_title, [value], units)
