# Copyright 2016 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 json
import logging
import os
import pickle
import re

from devil import base_error
from devil.utils import cmd_helper
from pylib import constants
from pylib.base import base_test_result
from pylib.base import test_instance
from pylib.constants import host_paths
from pylib.utils import test_filter


_GIT_CR_POS_RE = re.compile(r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$')


def _GetPersistedResult(test_name):
  file_name = os.path.join(constants.PERF_OUTPUT_DIR, test_name)
  if not os.path.exists(file_name):
    logging.error('File not found %s', file_name)
    return None

  with file(file_name, 'r') as f:
    return pickle.load(f)


def _GetChromiumRevision():
  # pylint: disable=line-too-long
  """Get the git hash and commit position of the chromium master branch.

  See:
  https://chromium.googlesource.com/chromium/tools/build/+/387e3cf3/scripts/slave/runtest.py#211

  Returns:
    A dictionary with 'revision' and 'commit_pos' keys.
  """
  # pylint: enable=line-too-long
  status, output = cmd_helper.GetCmdStatusAndOutput(
      ['git', 'log', '-n', '1', '--pretty=format:%H%n%B', 'HEAD'],
      cwd=host_paths.DIR_SOURCE_ROOT)
  revision = None
  commit_pos = None
  if not status:
    lines = output.splitlines()
    revision = lines[0]
    for line in reversed(lines):
      m = _GIT_CR_POS_RE.match(line.strip())
      if m:
        commit_pos = int(m.group(1))
        break
  return {'revision': revision, 'commit_pos': commit_pos}


class PerfTestInstance(test_instance.TestInstance):
  def __init__(self, args, _):
    super(PerfTestInstance, self).__init__()

    self._collect_chartjson_data = args.collect_chartjson_data
    self._dry_run = args.dry_run
    self._output_dir_archive_path = args.output_dir_archive_path
    # TODO(rnephew): Get rid of this when everything uses
    # --output-dir-archive-path
    if self._output_dir_archive_path is None and args.get_output_dir_archive:
      self._output_dir_archive_path = args.get_output_dir_archive
    self._known_devices_file = args.known_devices_file
    self._max_battery_temp = args.max_battery_temp
    self._min_battery_level = args.min_battery_level
    self._no_timeout = args.no_timeout
    self._output_chartjson_data = args.output_chartjson_data
    self._output_json_list = args.output_json_list
    self._print_step = args.print_step
    self._single_step = (
        ' '.join(args.single_step_command) if args.single_step else None)
    self._steps = args.steps
    self._test_filter = test_filter.InitializeFilterFromArgs(args)
    self._write_buildbot_json = args.write_buildbot_json

  #override
  def SetUp(self):
    pass

  #override
  def TearDown(self):
    pass

  def OutputJsonList(self):
    try:
      with file(self._steps, 'r') as i:
        all_steps = json.load(i)

      step_values = []
      for k, v in all_steps['steps'].iteritems():
        data = {'test': k, 'device_affinity': v['device_affinity']}

        persisted_result = _GetPersistedResult(k)
        if persisted_result:
          data['start_time'] = persisted_result['start_time']
          data['end_time'] = persisted_result['end_time']
          data['total_time'] = persisted_result['total_time']
          data['has_archive'] = persisted_result['archive_bytes'] is not None
        step_values.append(data)

      with file(self.output_json_list, 'w') as o:
        o.write(json.dumps(step_values))
      return base_test_result.ResultType.PASS
    except KeyError:
      logging.exception('Persistent results file missing key.')
      return base_test_result.ResultType.FAIL

  def PrintTestOutput(self):
    """Helper method to print the output of previously executed test_name.

    Test_name is passed from the command line as print_step

    Returns:
      exit code generated by the test step.
    """
    persisted_result = _GetPersistedResult(self._print_step)
    if not persisted_result:
      raise PersistentDataError('No data for test %s found.' % self._print_step)
    logging.info('*' * 80)
    logging.info('Output from:')
    logging.info(persisted_result['cmd'])
    logging.info('*' * 80)

    output_formatted = ''
    persisted_outputs = persisted_result['output']
    for i in xrange(len(persisted_outputs)):
      output_formatted += '\n\nOutput from run #%d:\n\n%s' % (
          i, persisted_outputs[i])
    print output_formatted

    if self.output_chartjson_data:
      with file(self.output_chartjson_data, 'w') as f:
        f.write(persisted_result['chartjson'])

    if self.output_dir_archive_path:
      if persisted_result['archive_bytes'] is not None:
        with file(self.output_dir_archive_path, 'wb') as f:
          f.write(persisted_result['archive_bytes'])
      else:
        logging.error('The output dir was not archived.')
    if persisted_result['exit_code'] == 0:
      return base_test_result.ResultType.PASS
    return base_test_result.ResultType.FAIL

  #override
  def TestType(self):
    return 'perf'

  @staticmethod
  def ReadChartjsonOutput(output_dir):
    if not output_dir:
      return ''
    json_output_path = os.path.join(output_dir, 'results-chart.json')
    try:
      with open(json_output_path) as f:
        return f.read()
    except IOError:
      logging.exception('Exception when reading chartjson.')
      logging.error('This usually means that telemetry did not run, so it could'
                    ' not generate the file. Please check the device running'
                    ' the test.')
      return ''

  def WriteBuildBotJson(self, output_dir):
    """Write metadata about the buildbot environment to the output dir."""
    if not output_dir or not self._write_buildbot_json:
      return
    data = {
      'chromium': _GetChromiumRevision(),
      'environment': dict(os.environ)
    }
    with open(os.path.join(output_dir, 'buildbot.json'), 'w') as f:
      json.dump(data, f, sort_keys=True, separators=(',', ': '))

  @property
  def collect_chartjson_data(self):
    return self._collect_chartjson_data

  @property
  def dry_run(self):
    return self._dry_run

  @property
  def known_devices_file(self):
    return self._known_devices_file

  @property
  def max_battery_temp(self):
    return self._max_battery_temp

  @property
  def min_battery_level(self):
    return self._min_battery_level

  @property
  def no_timeout(self):
    return self._no_timeout

  @property
  def output_chartjson_data(self):
    return self._output_chartjson_data

  @property
  def output_dir_archive_path(self):
    return self._output_dir_archive_path

  @property
  def output_json_list(self):
    return self._output_json_list

  @property
  def print_step(self):
    return self._print_step

  @property
  def single_step(self):
    return self._single_step

  @property
  def steps(self):
    return self._steps

  @property
  def test_filter(self):
    return self._test_filter


class PersistentDataError(base_error.BaseError):
  def __init__(self, message):
    super(PersistentDataError, self).__init__(message)
    self._is_infra_error = True
