# Copyright 2013 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 logging
import os
import subprocess
import sys
import tempfile

from telemetry.core import exceptions
from telemetry.internal.platform import profiler
from telemetry.internal.platform.profiler import android_profiling_helper


class _SingleProcessVTuneProfiler(object):
  """An internal class for using vtune for a given process."""
  def __init__(self, pid, output_file, browser_backend, platform_backend):
    self._pid = pid
    self._browser_backend = browser_backend
    self._platform_backend = platform_backend
    self._output_file = output_file
    self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
    cmd = ['amplxe-cl', '-collect', 'hotspots',
           '-target-pid', str(pid), '-r', self._output_file]
    self._is_android = platform_backend.GetOSName() == 'android'
    if self._is_android:
      cmd += ['-target-system', 'android']

    self._proc = subprocess.Popen(
        cmd, stdout=self._tmp_output_file, stderr=subprocess.STDOUT)

  def CollectProfile(self):
    if 'renderer' in self._output_file:
      try:
        self._platform_backend.GetCommandLine(self._pid)
      except exceptions.ProcessGoneException:
        logging.warning('Renderer was swapped out during profiling. '
                        'To collect a full profile rerun with '
                        '"--extra-browser-args=--single-process"')
    subprocess.call(['amplxe-cl', '-command', 'stop', '-r', self._output_file])

    exit_code = self._proc.wait()
    try:
      # 1: amplxe: Error: Cannot find a running process with the specified ID.
      #    Provide a valid PID.
      if exit_code not in (0, 1):
        raise Exception(
            'amplxe-cl failed with exit code %d. Output:\n%s' % (exit_code,
            self._GetStdOut()))
    finally:
      self._tmp_output_file.close()

    if exit_code:
      # The renderer process was swapped out. Now that we made sure VTune has
      # stopped, return without further processing the invalid profile.
      return self._output_file

    if self._is_android:
      required_libs = \
          android_profiling_helper.GetRequiredLibrariesForVTuneProfile(
              self._output_file)

      device = self._browser_backend.device
      symfs_root = os.path.dirname(self._output_file)
      android_profiling_helper.CreateSymFs(device,
                                           symfs_root,
                                           required_libs,
                                           use_symlinks=True)
      logging.info('Resolving symbols in profile.')
      subprocess.call(['amplxe-cl', '-finalize', '-r', self._output_file,
                       '-search-dir', symfs_root])

    print 'To view the profile, run:'
    print '  amplxe-gui %s' % self._output_file

    return self._output_file

  def _GetStdOut(self):
    self._tmp_output_file.flush()
    try:
      with open(self._tmp_output_file.name) as f:
        return f.read()
    except IOError:
      return ''


class VTuneProfiler(profiler.Profiler):

  def __init__(self, browser_backend, platform_backend, output_path, state):
    super(VTuneProfiler, self).__init__(
        browser_backend, platform_backend, output_path, state)
    process_output_file_map = self._GetProcessOutputFileMap()
    self._process_profilers = []

    has_renderer = False
    for pid, output_file in process_output_file_map.iteritems():
      if 'renderer' in output_file:
        has_renderer = True
        break

    for pid, output_file in process_output_file_map.iteritems():
      if has_renderer:
        if not 'renderer' in output_file:
          continue
      elif not 'browser0' in output_file:
        continue

      self._process_profilers.append(
          _SingleProcessVTuneProfiler(pid, output_file, browser_backend,
                                      platform_backend))

  @classmethod
  def name(cls):
    return 'vtune'

  @classmethod
  def is_supported(cls, browser_type):
    if sys.platform != 'linux2':
      return False
    if browser_type.startswith('cros'):
      return False
    try:
      proc = subprocess.Popen(['amplxe-cl', '-version'],
                              stderr=subprocess.STDOUT,
                              stdout=subprocess.PIPE)
      proc.communicate()
      if proc.returncode != 0:
        return False

      if browser_type.startswith('android'):
        # VTune checks if 'su' is available on the device.
        proc = subprocess.Popen(['adb', 'shell', 'su', '-c', 'id'],
                                stderr=subprocess.STDOUT,
                                stdout=subprocess.PIPE)
        return 'not found' not in proc.communicate()[0]

      return True
    except OSError:
      return False

  @classmethod
  def CustomizeBrowserOptions(cls, browser_type, options):
    options.AppendExtraBrowserArgs([
        '--no-sandbox',
        '--allow-sandbox-debugging',
    ])

  def CollectProfile(self):
    print 'Processing profile, this will take a few minutes...'

    output_files = []
    for single_process in self._process_profilers:
      output_files.append(single_process.CollectProfile())
    return output_files
