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

import collections
import logging
import os
import plistlib
import shutil
import tempfile
import xml.parsers.expat

from telemetry.core import os_version
from telemetry.core import util
from telemetry import decorators
from telemetry.internal.platform import power_monitor


# TODO: rename this class (seems like this is used by mac)
class PowerMetricsPowerMonitor(power_monitor.PowerMonitor):

  def __init__(self, backend):
    super(PowerMetricsPowerMonitor, self).__init__()
    self._powermetrics_process = None
    self._backend = backend
    self._output_filename = None
    self._output_directory = None

  @property
  def binary_path(self):
    return '/usr/bin/powermetrics'

  def StartMonitoringPower(self, browser):
    self._CheckStart()
    # Empirically powermetrics creates an empty output file immediately upon
    # starting.  We detect file creation as a signal that measurement has
    # started.  In order to avoid various race conditions in tempfile creation
    # we create a temp directory and have powermetrics create it's output
    # there rather than say, creating a tempfile, deleting it and reusing its
    # name.
    self._output_directory = tempfile.mkdtemp()
    self._output_filename = os.path.join(self._output_directory,
                                         'powermetrics.output')
    args = ['-f', 'plist',
            '-u', self._output_filename,
            '-i0',
            '--show-usage-summary']
    self._powermetrics_process = self._backend.LaunchApplication(
        self.binary_path, args, elevate_privilege=True)

    # Block until output file is written to ensure this function call is
    # synchronous in respect to powermetrics starting.
    def _OutputFileExists():
      return os.path.isfile(self._output_filename)
    util.WaitFor(_OutputFileExists, 1)

  @decorators.Cache
  def CanMonitorPower(self):
    mavericks_or_later = (
        self._backend.GetOSVersionName() >= os_version.MAVERICKS)
    binary_path = self.binary_path
    return mavericks_or_later and self._backend.CanLaunchApplication(
        binary_path)

  @staticmethod
  def _ParsePlistString(plist_string):
    """Wrapper to parse a plist from a string and catch any errors.

    Sometimes powermetrics will exit in the middle of writing it's output,
    empirically it seems that it always writes at least one sample in it's
    entirety so we can safely ignore any errors in it's output.

    Returns:
        Parser output on successful parse, None on parse error.
    """
    try:
      return plistlib.readPlistFromString(plist_string)
    except xml.parsers.expat.ExpatError:
      return None

  @staticmethod
  def ParsePowerMetricsOutput(powermetrics_output):
    """Parse output of powermetrics command line utility.

    Returns:
        Dictionary in the format returned by StopMonitoringPower() or None
        if |powermetrics_output| is empty - crbug.com/353250 .
    """
    if len(powermetrics_output) == 0:
      logging.warning('powermetrics produced zero length output')
      return {}

    # Container to collect samples for running averages.
    # out_path - list containing the key path in the output dictionary.
    # src_path - list containing the key path to get the data from in
    #    powermetrics' output.
    def ConstructMetric(out_path, src_path):
      RunningAverage = collections.namedtuple('RunningAverage', [
          'out_path', 'src_path', 'samples'])
      return RunningAverage(out_path, src_path, [])

    # List of RunningAverage objects specifying metrics we want to aggregate.
    metrics = [
        ConstructMetric(
            ['platform_info', 'average_frequency_hz'],
            ['processor', 'freq_hz']),
        ConstructMetric(
            ['platform_info', 'idle_percent'],
            ['processor', 'packages', 0, 'c_state_ratio'])]

    def DataWithMetricKeyPath(metric, powermetrics_output):
      """Retrieve the sample from powermetrics' output for a given metric.

      Args:
          metric: The RunningAverage object we want to collect a new sample for.
          powermetrics_output: Dictionary containing powermetrics output.

      Returns:
          The sample corresponding to |metric|'s keypath."""
      # Get actual data corresponding to key path.
      out_data = powermetrics_output
      for k in metric.src_path:
        out_data = out_data[k]

      assert type(out_data) in [int, float], (
          'Was expecting a number: %s (%s)' % (type(out_data), out_data))
      return float(out_data)

    sample_durations = []
    total_energy_consumption_mwh = 0
    # powermetrics outputs multiple plists separated by null terminators.
    raw_plists = powermetrics_output.split('\0')
    raw_plists = [x for x in raw_plists if len(x) > 0]
    assert len(raw_plists) == 1

    # -------- Examine contents of first plist for systems specs. --------
    plist = PowerMetricsPowerMonitor._ParsePlistString(raw_plists[0])
    if not plist:
      logging.warning('powermetrics produced invalid output, output length: '
                      '%d', len(powermetrics_output))
      return {}

    # Powermetrics doesn't record power usage when running on a VM.
    hw_model = plist.get('hw_model')
    if hw_model and hw_model.startswith('VMware'):
      return {}

    if 'GPU' in plist:
      metrics.extend([
          ConstructMetric(
              ['component_utilization', 'gpu', 'average_frequency_hz'],
              ['GPU', 0, 'freq_hz']),
          ConstructMetric(
              ['component_utilization', 'gpu', 'idle_percent'],
              ['GPU', 0, 'c_state_ratio'])])

    # There's no way of knowing ahead of time how many cpus and packages the
    # current system has. Iterate over cores and cpus - construct metrics for
    # each one.
    if 'processor' in plist:
      core_dict = plist['processor']['packages'][0]['cores']
      num_cores = len(core_dict)
      cpu_num = 0
      for core_idx in xrange(num_cores):
        num_cpus = len(core_dict[core_idx]['cpus'])
        base_src_path = ['processor', 'packages', 0, 'cores', core_idx]
        for cpu_idx in xrange(num_cpus):
          base_out_path = ['component_utilization', 'cpu%d' % cpu_num]
          # C State ratio is per-package, component CPUs of that package may
          # have different frequencies.
          metrics.append(ConstructMetric(
              base_out_path + ['average_frequency_hz'],
              base_src_path + ['cpus', cpu_idx, 'freq_hz']))
          metrics.append(ConstructMetric(
              base_out_path + ['idle_percent'],
              base_src_path + ['c_state_ratio']))
          cpu_num += 1

    # -------- Parse Data Out of Plists --------
    plist = PowerMetricsPowerMonitor._ParsePlistString(raw_plists[0])
    if not plist:
      logging.error('Error parsing plist.')
      return {}

    # Duration of this sample.
    sample_duration_ms = int(plist['elapsed_ns']) / 10 ** 6
    sample_durations.append(sample_duration_ms)

    if 'processor' not in plist:
      logging.error("'processor' field not found in plist.")
      return {}
    processor = plist['processor']

    total_energy_consumption_mwh = (
        (float(processor.get('package_joules', 0)) / 3600.) * 10 ** 3)

    for m in metrics:
      try:
        m.samples.append(DataWithMetricKeyPath(m, plist))
      except KeyError:
        # Old CPUs don't have c-states, so if data is missing, just ignore it.
        logging.info('Field missing from powermetrics output: %s', m.src_path)
        continue

    # -------- Collect and Process Data --------
    out_dict = {}
    out_dict['identifier'] = 'powermetrics'
    out_dict['energy_consumption_mwh'] = total_energy_consumption_mwh

    def StoreMetricAverage(metric, sample_durations, out):
      """Calculate average value of samples in a metric and store in output
         path as specified by metric.

      Args:
          metric: A RunningAverage object containing samples to average.
          sample_durations: A list which parallels the samples list containing
              the time slice for each sample.
          out: The output dicat, average is stored in the location specified by
              metric.out_path.
      """
      if len(metric.samples) == 0:
        return

      assert len(metric.samples) == len(sample_durations)
      avg = 0
      for i in xrange(len(metric.samples)):
        avg += metric.samples[i] * sample_durations[i]
      avg /= sum(sample_durations)

      # Store data in output, creating empty dictionaries as we go.
      for k in metric.out_path[:-1]:
        if not out.has_key(k):
          out[k] = {}
        out = out[k]
      out[metric.out_path[-1]] = avg

    for m in metrics:
      StoreMetricAverage(m, sample_durations, out_dict)

    if 'tasks' not in plist:
      logging.error("'tasks' field not found in plist.")
      return {}

    # The following CPU metrics are already time-normalized, and segmented by
    # process. Sum the metrics across all Chrome processes.
    cputime = 0
    energy_impact = 0
    browser_process_count = 0
    idle_wakeups = 0
    for task in plist['tasks']:
      if 'Chrome' in task['name'] or 'Chromium' in task['name']:
        if 'Helper' not in task['name']:
          browser_process_count += 1
        cputime += float(task['cputime_ms_per_s'])
        energy_impact += float(task.get('energy_impact', 0))
        idle_wakeups += float(task['idle_wakeups_per_s'])
    if browser_process_count == 0:
      logging.warning('No Chrome or Chromium browser process found with '
                      'powermetrics. Chrome CPU metrics will not be emitted.')
      return {}
    elif browser_process_count >= 2:
      logging.warning('powermetrics found more than one Chrome or Chromium '
                      'browser. Chrome CPU metrics will not be emitted.')
      # During Telemetry unit tests, there may be multiple Chrome browsers
      # present. Don't add cpu metrics, but don't return {} either.
    else:  # browser_process_count == 1:
      chrome_dict = {}
      chrome_dict['cputime_ms_per_s'] = cputime
      chrome_dict['energy_impact'] = energy_impact
      chrome_dict['idle_wakeups_per_s'] = idle_wakeups
      out_dict['component_utilization']['chrome'] = chrome_dict

    return out_dict

  def _KillPowerMetricsProcess(self):
    """Kill a running powermetrics process."""
    try:
      if self._powermetrics_process.poll() is None:
        self._powermetrics_process.terminate()
    except OSError as e:
      logging.warning(
          'Error when trying to terminate powermetric process: %s', repr(e))
      if self._powermetrics_process.poll() is None:
        # terminate() can fail when Powermetrics does not have the SetUID set.
        self._backend.LaunchApplication(
          '/usr/bin/pkill',
          ['-SIGTERM', os.path.basename(self.binary_path)],
          elevate_privilege=True)

  def StopMonitoringPower(self):
    self._CheckStop()
    # Tell powermetrics to take an immediate sample.
    try:
      self._KillPowerMetricsProcess()
      (power_stdout, power_stderr) = self._powermetrics_process.communicate()
      returncode = self._powermetrics_process.returncode
      assert returncode in [0, -15], (
          """powermetrics error
          return code=%d
          stdout=(%s)
          stderr=(%s)""" % (returncode, power_stdout, power_stderr))

      with open(self._output_filename, 'rb') as output_file:
        powermetrics_output = output_file.read()
      return PowerMetricsPowerMonitor.ParsePowerMetricsOutput(
          powermetrics_output)
    except Exception as e:
      logging.warning(
          'Error when trying to collect power monitoring data: %s', repr(e))
      return PowerMetricsPowerMonitor.ParsePowerMetricsOutput('')
    finally:
      shutil.rmtree(self._output_directory)
      self._output_directory = None
      self._output_filename = None
      self._powermetrics_process = None
