# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import io
import logging
import os
import time

from mobly import logger as mobly_logger
from mobly import utils
from mobly.controllers.android_device_lib import adb
from mobly.controllers.android_device_lib import errors
from mobly.controllers.android_device_lib.services import base_service

CREATE_LOGCAT_FILE_TIMEOUT_SEC = 5


class Error(errors.ServiceError):
  """Root error type for logcat service."""
  SERVICE_TYPE = 'Logcat'


class Config(object):
  """Config object for logcat service.

  Attributes:
    clear_log: bool, clears the logcat before collection if True.
    logcat_params: string, extra params to be added to logcat command.
    output_file_path: string, the path on the host to write the log file
      to, including the actual filename. The service will automatically
      generate one if not specified.
  """

  def __init__(self, logcat_params=None, clear_log=True, output_file_path=None):
    self.clear_log = clear_log
    self.logcat_params = logcat_params if logcat_params else ''
    self.output_file_path = output_file_path


class Logcat(base_service.BaseService):
  """Android logcat service for Mobly's AndroidDevice controller.

  Attributes:
    adb_logcat_file_path: string, path to the file that the service writes
      adb logcat to by default.
  """
  OUTPUT_FILE_TYPE = 'logcat'

  def __init__(self, android_device, configs=None):
    super().__init__(android_device, configs)
    self._ad = android_device
    self._adb_logcat_process = None
    self._adb_logcat_file_obj = None
    self.adb_logcat_file_path = None
    # Logcat service uses a single config obj, using singular internal
    # name: `_config`.
    self._config = configs if configs else Config()

  def _enable_logpersist(self):
    """Attempts to enable logpersist daemon to persist logs."""
    # Logpersist is only allowed on rootable devices because of excessive
    # reads/writes for persisting logs.
    if not self._ad.is_rootable:
      return

    logpersist_warning = ('%s encountered an error enabling persistent'
                          ' logs, logs may not get saved.')
    # Android L and older versions do not have logpersist installed,
    # so check that the logpersist scripts exists before trying to use
    # them.
    if not self._ad.adb.has_shell_command('logpersist.start'):
      logging.warning(logpersist_warning, self)
      return

    try:
      # Disable adb log spam filter for rootable devices. Have to stop
      # and clear settings first because 'start' doesn't support --clear
      # option before Android N.
      self._ad.adb.shell('logpersist.stop --clear')
      self._ad.adb.shell('logpersist.start')
    except adb.AdbError:
      logging.warning(logpersist_warning, self)

  def _is_timestamp_in_range(self, target, begin_time, end_time):
    low = mobly_logger.logline_timestamp_comparator(begin_time, target) <= 0
    high = mobly_logger.logline_timestamp_comparator(end_time, target) >= 0
    return low and high

  def create_output_excerpts(self, test_info):
    """Convenient method for creating excerpts of adb logcat.

    This copies logcat lines from self.adb_logcat_file_path to an excerpt
    file, starting from the location where the previous excerpt ended.

    Call this method at the end of: `setup_class`, `teardown_test`, and
    `teardown_class`.

    Args:
      test_info: `self.current_test_info` in a Mobly test.

    Returns:
      List of strings, the absolute paths to excerpt files.
    """
    dest_path = test_info.output_path
    utils.create_dir(dest_path)
    filename = self._ad.generate_filename(self.OUTPUT_FILE_TYPE, test_info,
                                          'txt')
    excerpt_file_path = os.path.join(dest_path, filename)
    with io.open(excerpt_file_path, 'w', encoding='utf-8',
                 errors='replace') as out:
      # Devices may accidentally go offline during test,
      # check not None before readline().
      while self._adb_logcat_file_obj:
        line = self._adb_logcat_file_obj.readline()
        if not line:
          break
        out.write(line)
    self._ad.log.debug('logcat excerpt created at: %s', excerpt_file_path)
    return [excerpt_file_path]

  @property
  def is_alive(self):
    return True if self._adb_logcat_process else False

  def clear_adb_log(self):
    """Clears cached adb content."""
    try:
      self._ad.adb.logcat('-c')
    except adb.AdbError as e:
      # On Android O, the clear command fails due to a known bug.
      # Catching this so we don't crash from this Android issue.
      if b'failed to clear' in e.stderr:
        self._ad.log.warning('Encountered known Android error to clear logcat.')
      else:
        raise

  def _assert_not_running(self):
    """Asserts the logcat service is not running.

    Raises:
      Error, if the logcat service is running.
    """
    if self.is_alive:
      raise Error(
          self._ad,
          'Logcat thread is already running, cannot start another one.')

  def update_config(self, new_config):
    """Updates the configuration for the service.

    The service needs to be stopped before updating, and explicitly started
    after the update.

    This will reset the service. Previous output files may be orphaned if
    output path is changed.

    Args:
      new_config: Config, the new config to use.
    """
    self._assert_not_running()
    self._ad.log.info('[LogcatService] Changing config from %s to %s',
                      self._config, new_config)
    self._config = new_config

  def _open_logcat_file(self):
    """Create a file object that points to the beginning of the logcat file.
    Wait for the logcat file to be created by the subprocess if it doesn't
    exist.
    """
    if not self._adb_logcat_file_obj:
      start_time = time.time()
      while not os.path.exists(self.adb_logcat_file_path):
        if time.time() > start_time + CREATE_LOGCAT_FILE_TIMEOUT_SEC:
          raise Error(self._ad,
                      'Timeout while waiting for logcat file to be created.')
        time.sleep(1)
      self._adb_logcat_file_obj = io.open(self.adb_logcat_file_path,
                                          'r',
                                          encoding='utf-8',
                                          errors='replace')
      self._adb_logcat_file_obj.seek(0, os.SEEK_END)

  def _close_logcat_file(self):
    """Closes and resets the logcat file object, if it exists."""
    if self._adb_logcat_file_obj:
      self._adb_logcat_file_obj.close()
      self._adb_logcat_file_obj = None

  def start(self):
    """Starts a standing adb logcat collection.

    The collection runs in a separate subprocess and saves logs in a file.
    """
    self._assert_not_running()
    if self._config.clear_log:
      self.clear_adb_log()
    self._start()
    self._open_logcat_file()

  def _start(self):
    """The actual logic of starting logcat."""
    self._enable_logpersist()
    if self._config.output_file_path:
      self._close_logcat_file()
      self.adb_logcat_file_path = self._config.output_file_path
    if not self.adb_logcat_file_path:
      f_name = self._ad.generate_filename(self.OUTPUT_FILE_TYPE,
                                          extension_name='txt')
      logcat_file_path = os.path.join(self._ad.log_path, f_name)
      self.adb_logcat_file_path = logcat_file_path
    utils.create_dir(os.path.dirname(self.adb_logcat_file_path))
    # In debugging mode of IntelijIDEA, "patch_args" remove
    # double quotes in args if starting and ending with it.
    # Add spaces at beginning and at last to fix this issue.
    cmd = ' "%s" -s %s logcat -v threadtime -T 1 %s >> "%s" ' % (
        adb.ADB, self._ad.serial, self._config.logcat_params,
        self.adb_logcat_file_path)
    process = utils.start_standing_subprocess(cmd, shell=True)
    self._adb_logcat_process = process

  def stop(self):
    """Stops the adb logcat service."""
    self._close_logcat_file()
    self._stop()

  def _stop(self):
    """Stops the background process for logcat."""
    if not self._adb_logcat_process:
      return
    try:
      utils.stop_standing_subprocess(self._adb_logcat_process)
    except:
      self._ad.log.exception('Failed to stop adb logcat.')
    self._adb_logcat_process = None

  def pause(self):
    """Pauses logcat.

    Note: the service is unable to collect the logs when paused, if more
    logs are generated on the device than the device's log buffer can hold,
    some logs would be lost.
    """
    self._stop()

  def resume(self):
    """Resumes a paused logcat service."""
    self._assert_not_running()
    # Not clearing the log regardless of the config when resuming.
    # Otherwise the logs during the paused time will be lost.
    self._start()
