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

"""Environment setup and teardown for remote devices."""

import distutils.version
import json
import logging
import os
import random
import sys

from pylib import constants
from pylib.base import environment
from pylib.remote.device import appurify_sanitized
from pylib.remote.device import remote_device_helper

class RemoteDeviceEnvironment(environment.Environment):
  """An environment for running on remote devices."""

  _ENV_KEY = 'env'
  _DEVICE_KEY = 'device'

  def __init__(self, args, error_func):
    """Constructor.

    Args:
      args: Command line arguments.
      error_func: error to show when using bad command line arguments.
    """
    super(RemoteDeviceEnvironment, self).__init__()
    self._access_token = None
    self._device = None
    self._device_type = args.device_type
    self._verbose_count = args.verbose_count
    self._timeouts = {
        'queueing': 60 * 10,
        'installing': 60 * 10,
        'in-progress': 60 * 30,
        'unknown': 60 * 5
    }
    # Example config file:
    # {
    #   "remote_device": ["Galaxy S4", "Galaxy S3"],
    #   "remote_device_os": ["4.4.2", "4.4.4"],
    #   "remote_device_minimum_os": "4.4.2",
    #   "api_address": "www.example.com",
    #   "api_port": "80",
    #   "api_protocol": "http",
    #   "api_secret": "apisecret",
    #   "api_key": "apikey",
    #   "timeouts": {
    #     "queueing": 600,
    #     "installing": 600,
    #     "in-progress": 1800,
    #     "unknown": 300
    #   }
    # }
    if args.remote_device_file:
      with open(args.remote_device_file) as device_file:
        device_json = json.load(device_file)
    else:
      device_json = {}

    self._api_address = device_json.get('api_address', None)
    self._api_key = device_json.get('api_key', None)
    self._api_port = device_json.get('api_port', None)
    self._api_protocol = device_json.get('api_protocol', None)
    self._api_secret = device_json.get('api_secret', None)
    self._device_oem = device_json.get('device_oem', None)
    self._device_type = device_json.get('device_type', 'Android')
    self._remote_device = device_json.get('remote_device', None)
    self._remote_device_minimum_os = device_json.get(
        'remote_device_minimum_os', None)
    self._remote_device_os = device_json.get('remote_device_os', None)
    self._results_path = device_json.get('results_path', None)
    self._runner_package = device_json.get('runner_package', None)
    self._runner_type = device_json.get('runner_type', None)
    if 'timeouts' in device_json:
      for key in device_json['timeouts']:
        self._timeouts[key] = device_json['timeouts'][key]

    def command_line_override(
        file_value, cmd_line_value, desc, print_value=True):
      if cmd_line_value:
        if file_value and file_value != cmd_line_value:
          if print_value:
            logging.info('Overriding %s from %s to %s',
                         desc, file_value, cmd_line_value)
          else:
            logging.info('overriding %s', desc)
        return cmd_line_value
      return file_value

    self._api_address = command_line_override(
        self._api_address, args.api_address, 'api_address')
    self._api_port = command_line_override(
        self._api_port, args.api_port, 'api_port')
    self._api_protocol = command_line_override(
        self._api_protocol, args.api_protocol, 'api_protocol')
    self._device_oem = command_line_override(
        self._device_oem, args.device_oem, 'device_oem')
    self._device_type = command_line_override(
        self._device_type, args.device_type, 'device_type')
    self._remote_device = command_line_override(
        self._remote_device, args.remote_device, 'remote_device')
    self._remote_device_minimum_os = command_line_override(
        self._remote_device_minimum_os, args.remote_device_minimum_os,
        'remote_device_minimum_os')
    self._remote_device_os = command_line_override(
        self._remote_device_os, args.remote_device_os, 'remote_device_os')
    self._results_path = command_line_override(
        self._results_path, args.results_path, 'results_path')
    self._runner_package = command_line_override(
        self._runner_package, args.runner_package, 'runner_package')
    self._runner_type = command_line_override(
        self._runner_type, args.runner_type, 'runner_type')

    if args.api_key_file:
      with open(args.api_key_file) as api_key_file:
        temp_key = api_key_file.read().strip()
        self._api_key = command_line_override(
            self._api_key, temp_key, 'api_key', print_value=False)
    self._api_key = command_line_override(
        self._api_key, args.api_key, 'api_key', print_value=False)

    if args.api_secret_file:
      with open(args.api_secret_file) as api_secret_file:
        temp_secret = api_secret_file.read().strip()
        self._api_secret = command_line_override(
            self._api_secret, temp_secret, 'api_secret', print_value=False)
    self._api_secret = command_line_override(
        self._api_secret, args.api_secret, 'api_secret', print_value=False)

    if not self._api_address:
      error_func('Must set api address with --api-address'
                 ' or in --remote-device-file.')
    if not self._api_key:
      error_func('Must set api key with --api-key, --api-key-file'
                 ' or in --remote-device-file')
    if not self._api_port:
      error_func('Must set api port with --api-port'
                 ' or in --remote-device-file')
    if not self._api_protocol:
      error_func('Must set api protocol with --api-protocol'
                 ' or in --remote-device-file. Example: http')
    if not self._api_secret:
      error_func('Must set api secret with --api-secret, --api-secret-file'
                 ' or in --remote-device-file')

    logging.info('Api address: %s', self._api_address)
    logging.info('Api port: %s', self._api_port)
    logging.info('Api protocol: %s', self._api_protocol)
    logging.info('Remote device: %s', self._remote_device)
    logging.info('Remote device minimum OS: %s',
                 self._remote_device_minimum_os)
    logging.info('Remote device OS: %s', self._remote_device_os)
    logging.info('Remote device OEM: %s', self._device_oem)
    logging.info('Remote device type: %s', self._device_type)
    logging.info('Results Path: %s', self._results_path)
    logging.info('Runner package: %s', self._runner_package)
    logging.info('Runner type: %s', self._runner_type)
    logging.info('Timeouts: %s', self._timeouts)

    if not args.trigger and not args.collect:
      self._trigger = True
      self._collect = True
    else:
      self._trigger = args.trigger
      self._collect = args.collect

  def SetUp(self):
    """Set up the test environment."""
    os.environ['APPURIFY_API_PROTO'] = self._api_protocol
    os.environ['APPURIFY_API_HOST'] = self._api_address
    os.environ['APPURIFY_API_PORT'] = self._api_port
    self._GetAccessToken()
    if self._trigger:
      self._device = self._SelectDevice()

  def TearDown(self):
    """Teardown the test environment."""
    self._RevokeAccessToken()

  def __enter__(self):
    """Set up the test run when used as a context manager."""
    try:
      self.SetUp()
      return self
    except:
      self.__exit__(*sys.exc_info())
      raise

  def __exit__(self, exc_type, exc_val, exc_tb):
    """Tears down the test run when used as a context manager."""
    self.TearDown()

  def DumpTo(self, persisted_data):
    env_data = {
      self._DEVICE_KEY: self._device,
    }
    persisted_data[self._ENV_KEY] = env_data

  def LoadFrom(self, persisted_data):
    env_data = persisted_data[self._ENV_KEY]
    self._device = env_data[self._DEVICE_KEY]

  def _GetAccessToken(self):
    """Generates access token for remote device service."""
    logging.info('Generating remote service access token')
    with appurify_sanitized.SanitizeLogging(self._verbose_count,
                                            logging.WARNING):
      access_token_results = appurify_sanitized.api.access_token_generate(
          self._api_key, self._api_secret)
    remote_device_helper.TestHttpResponse(access_token_results,
                                          'Unable to generate access token.')
    self._access_token = access_token_results.json()['response']['access_token']

  def _RevokeAccessToken(self):
    """Destroys access token for remote device service."""
    logging.info('Revoking remote service access token')
    with appurify_sanitized.SanitizeLogging(self._verbose_count,
                                            logging.WARNING):
      revoke_token_results = appurify_sanitized.api.access_token_revoke(
          self._access_token)
    remote_device_helper.TestHttpResponse(revoke_token_results,
                                          'Unable to revoke access token.')

  def _SelectDevice(self):
    """Select which device to use."""
    logging.info('Finding device to run tests on.')
    with appurify_sanitized.SanitizeLogging(self._verbose_count,
                                            logging.WARNING):
      dev_list_res = appurify_sanitized.api.devices_list(self._access_token)
    remote_device_helper.TestHttpResponse(dev_list_res,
                                          'Unable to generate access token.')
    device_list = dev_list_res.json()['response']
    random.shuffle(device_list)
    for device in device_list:
      if device['os_name'] != self._device_type:
        continue
      if self._remote_device and device['name'] not in self._remote_device:
        continue
      if (self._remote_device_os
          and device['os_version'] not in self._remote_device_os):
        continue
      if self._device_oem and device['brand'] not in self._device_oem:
        continue
      if (self._remote_device_minimum_os
          and distutils.version.LooseVersion(device['os_version'])
          < distutils.version.LooseVersion(self._remote_device_minimum_os)):
        continue
      if ((self._remote_device and self._remote_device_os)
          or device['available_devices_count']):
        logging.info('Found device: %s %s',
                     device['name'], device['os_version'])
        return device
    self._NoDeviceFound(device_list)

  def _PrintAvailableDevices(self, device_list):
    def compare_devices(a,b):
      for key in ('os_version', 'name'):
        c = cmp(a[key], b[key])
        if c:
          return c
      return 0

    logging.critical('Available %s Devices:', self._device_type)
    devices = (d for d in device_list if d['os_name'] == self._device_type)
    for d in sorted(devices, compare_devices):
      logging.critical('  %s %s', d['os_version'].ljust(7), d['name'])

  def _NoDeviceFound(self, device_list):
    self._PrintAvailableDevices(device_list)
    raise remote_device_helper.RemoteDeviceError('No device found.')

  @property
  def collect(self):
    return self._collect

  @property
  def device_type_id(self):
    return self._device['device_type_id']

  @property
  def only_output_failures(self):
    # TODO(jbudorick): Remove this once b/18981674 is fixed.
    return True

  @property
  def results_path(self):
    return self._results_path

  @property
  def runner_package(self):
    return self._runner_package

  @property
  def runner_type(self):
    return self._runner_type

  @property
  def timeouts(self):
    return self._timeouts

  @property
  def token(self):
    return self._access_token

  @property
  def trigger(self):
    return self._trigger

  @property
  def verbose_count(self):
    return self._verbose_count

  @property
  def device_type(self):
    return self._device_type
