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

# This module has common mock objects and functions used in unit tests for
# mobly.controllers.android_device module.

from builtins import bytes

import logging
import mock
import os

DEFAULT_MOCK_PROPERTIES = {
    'ro.build.id': 'AB42',
    'ro.build.type': 'userdebug',
    'ro.build.product': 'FakeModel',
    'ro.build.version.codename': 'Z',
    'ro.build.version.sdk': '28',
    'ro.product.name': 'FakeModel',
    'ro.debuggable': '1',
    'sys.boot_completed': "1",
    'ro.build.characteristics': 'emulator,phone',
    'ro.hardware': 'marlin',
}


class Error(Exception):
  pass


def get_mock_ads(num):
  """Generates a list of mock AndroidDevice objects.

  The serial number of each device will be integer 0 through num - 1.

  Args:
    num: An integer that is the number of mock AndroidDevice objects to
      create.
  """
  ads = []
  for i in range(num):
    ad = mock.MagicMock(name="AndroidDevice", serial=str(i), h_port=None)
    ad.skip_logcat = False
    ads.append(ad)
  return ads


def get_all_instances():
  return get_mock_ads(5)


def get_instances(serials):
  ads = []
  for serial in serials:
    ad = mock.MagicMock(name="AndroidDevice", serial=serial, h_port=None)
    ads.append(ad)
  return ads


def get_instances_with_configs(dicts):
  return get_instances([d['serial'] for d in dicts])


def list_adb_devices():
  return [ad.serial for ad in get_mock_ads(5)]


class MockAdbProxy(object):
  """Mock class that swaps out calls to adb with mock calls."""

  def __init__(self,
               serial='',
               fail_br=False,
               fail_br_before_N=False,
               mock_properties=None,
               installed_packages=None,
               instrumented_packages=None):
    self.serial = serial
    self.fail_br = fail_br
    self.fail_br_before_N = fail_br_before_N
    self.getprops_call_count = 0
    if mock_properties is None:
      self.mock_properties = DEFAULT_MOCK_PROPERTIES.copy()
    else:
      self.mock_properties = mock_properties
    if installed_packages is None:
      installed_packages = []
    self.installed_packages = installed_packages
    if instrumented_packages is None:
      instrumented_packages = []
    self.installed_packages = installed_packages
    self.instrumented_packages = instrumented_packages

  def shell(self, params, timeout=None):
    if params == "id -u":
      return b"root"
    elif params == "bugreportz":
      if self.fail_br:
        return b"OMG I died!\n"
      return b'OK:/path/bugreport.zip\n'
    elif params == "bugreportz -v":
      if self.fail_br_before_N:
        return b"/system/bin/sh: bugreportz: not found"
      return b'1.1'
    elif 'pm list package' in params:
      packages = self.installed_packages + [
          package for package, _, _ in self.instrumented_packages
      ]
      return bytes('\n'.join(['package:%s' % package for package in packages]),
                   'utf-8')
    elif 'pm list instrumentation' in params:
      return bytes(
          '\n'.join([
              'instrumentation:%s/%s (target=%s)' % (package, runner, target)
              for package, runner, target in self.instrumented_packages
          ]), 'utf-8')
    elif 'which' in params:
      return b''

  def getprop(self, params):
    if params in self.mock_properties:
      return self.mock_properties[params]

  def getprops(self, params):
    self.getprops_call_count = self.getprops_call_count + 1
    return self.mock_properties

  def bugreport(self, args, shell=False, timeout=None):
    expected = os.path.join(
        logging.log_path, 'AndroidDevice%s' % self.serial, 'BugReports',
        'bugreport,test_something,%s,fakemodel,sometime' % self.serial)
    if expected not in args:
      raise Error('"Expected "%s", got "%s"' % (expected, args))

  def __getattr__(self, name):
    """All calls to the none-existent functions in adb proxy would
    simply return the adb command string.
    """

    def adb_call(*args, **kwargs):
      arg_str = ' '.join(str(elem) for elem in args)
      return arg_str

    return adb_call


class MockFastbootProxy(object):
  """Mock class that swaps out calls to adb with mock calls."""

  def __init__(self, serial):
    self.serial = serial

  def devices(self):
    return b"xxxx device\nyyyy device"

  def __getattr__(self, name):

    def fastboot_call(*args):
      arg_str = ' '.join(str(elem) for elem in args)
      return arg_str

    return fastboot_call
