# Copyright 2015 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 optparse
import os
import re

import py_utils

from devil.android import flag_changer
from devil.android.constants import webapk
from devil.android.perf import cache_control
from devil.android.sdk import intent

from systrace import trace_result
from systrace import tracing_agents


class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
  def __init__(self, device, package_info, webapk_package, cold, url,
               trace_time=None):
    tracing_agents.TracingAgent.__init__(self)
    self._device = device
    self._package_info = package_info
    self._webapk_package = webapk_package
    self._cold = cold
    self._logcat_monitor = self._device.GetLogcatMonitor()
    self._url = url
    self._trace_time = trace_time
    self._trace_file = None
    self._trace_finish_re = re.compile(r' Completed startup tracing to (.*)')
    self._flag_changer = flag_changer.FlagChanger(
      self._device, self._package_info.cmdline_file)

  def __repr__(self):
    return 'Browser Startup Trace'

  def _SetupTracing(self):
    # TODO(lizeb): Figure out how to clean up the command-line file when
    # _TearDownTracing() is not executed in StopTracing().
    flags = ['--trace-startup']
    if self._trace_time is not None:
      flags.append('--trace-startup-duration={}'.format(self._trace_time))
    self._flag_changer.AddFlags(flags)
    self._device.ForceStop(self._package_info.package)
    if self._webapk_package:
      self._device.ForceStop(self._webapk_package)
      logging.warning('Forces to stop the WebAPK and the browser provided by '
                      '--browser: %s. Please make sure that this browser '
                      'matches the host browser of the WebAPK %s. ',
                      self._package_info.package,
                      self._webapk_package)
    if self._cold:
      self._device.EnableRoot()
      cache_control.CacheControl(self._device).DropRamCaches()
    launch_intent = None
    if self._webapk_package:
      launch_intent = intent.Intent(
          package=self._webapk_package,
          activity=webapk.WEBAPK_MAIN_ACTIVITY,
          data=self._url)
    elif self._url == '':
      launch_intent = intent.Intent(
          action='android.intent.action.MAIN',
          package=self._package_info.package,
          activity=self._package_info.activity)
    else:
      launch_intent = intent.Intent(
          package=self._package_info.package,
          activity=self._package_info.activity,
          data=self._url,
          extras={'create_new_tab': True})
    self._logcat_monitor.Start()
    self._device.StartActivity(launch_intent, blocking=True)

  def _TearDownTracing(self):
    self._flag_changer.Restore()

  @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
  def StartAgentTracing(self, config, timeout=None):
    self._SetupTracing()
    return True

  @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
  def StopAgentTracing(self, timeout=None):
    try:
      self._trace_file = self._logcat_monitor.WaitFor(
          self._trace_finish_re).group(1)
    finally:
      self._TearDownTracing()
    return True

  @py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
  def GetResults(self, timeout=None):
    with open(self._PullTrace(), 'r') as f:
      trace_data = f.read()
    return trace_result.TraceResult('traceEvents', trace_data)

  def _PullTrace(self):
    trace_file = self._trace_file.replace('/storage/emulated/0/', '/sdcard/')
    host_file = os.path.join(os.path.curdir, os.path.basename(trace_file))
    self._device.PullFile(trace_file, host_file)
    return host_file

  def SupportsExplicitClockSync(self):
    return False

  def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
    # pylint: disable=unused-argument
    assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
        'recorded since explicit clock sync is not supported.')


class ChromeStartupConfig(tracing_agents.TracingConfig):
  def __init__(self, device, package_info, webapk_package, cold, url,
               chrome_categories, trace_time):
    tracing_agents.TracingConfig.__init__(self)
    self.device = device
    self.package_info = package_info
    self.webapk_package = webapk_package
    self.cold = cold
    self.url = url
    self.chrome_categories = chrome_categories
    self.trace_time = trace_time


def try_create_agent(config):
  return ChromeStartupTracingAgent(config.device, config.package_info,
                                   config.webapk_package,
                                   config.cold, config.url, config.trace_time)

def add_options(parser):
  options = optparse.OptionGroup(parser, 'Chrome startup tracing')
  options.add_option('--url', help='URL to visit on startup. Default: '
                     'https://www.google.com. An empty URL launches Chrome '
                     'with a MAIN action instead of VIEW.',
                     default='https://www.google.com', metavar='URL')
  options.add_option('--cold', help='Flush the OS page cache before starting '
                     'the browser. Note that this require a device with root '
                     'access.', default=False, action='store_true')
  options.add_option('--webapk-package', help='Specify the package name '
                     'of the WebAPK to launch the given URL. An empty URL '
                     'laucnhes the host browser of the WebAPK with an new '
                     'tab.', default=None)

  return options

def get_config(options):
  return ChromeStartupConfig(options.device, options.package_info,
                             options.webapk_package, options.cold,
                             options.url, options.chrome_categories,
                             options.trace_time)
