# Copyright (c) 2013 The Chromium OS 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 contextlib
import dbus
import logging
import random
import time

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros.cellular import cellular
from autotest_lib.client.cros.networking import cellular_proxy
from autotest_lib.client.cros.networking import shill_context
from autotest_lib.client.cros.networking import shill_proxy

# Number of seconds we wait for the cellular service to perform an action.
DEVICE_TIMEOUT=45
SERVICE_TIMEOUT=75

# Number of times and seconds between modem state checks to ensure that the
# modem is not in a temporary transition state.
NUM_MODEM_STATE_CHECKS=2
MODEM_STATE_CHECK_PERIOD_SECONDS=5

# Number of seconds to sleep after a connect request in slow-connect mode.
SLOW_CONNECT_WAIT_SECONDS=20


class TechnologyCommands():
    """Control the modem mostly using shill Technology interfaces."""
    def __init__(self, shill, command_delegate):
        self.shill = shill
        self.command_delegate = command_delegate

    def Enable(self):
        self.shill.manager.EnableTechnology(
                shill_proxy.ShillProxy.TECHNOLOGY_CELLULAR)

    def Disable(self):
        self.shill.manager.DisableTechnology(
                shill_proxy.ShillProxy.TECHNOLOGY_CELLULAR)

    def Connect(self, **kwargs):
        self.command_delegate.Connect(**kwargs)

    def Disconnect(self):
        return self.command_delegate.Disconnect()

    def __str__(self):
        return 'Technology Commands'


class ModemCommands():
    """Control the modem using modem manager DBUS interfaces."""
    def __init__(self, modem, slow_connect):
        self.modem = modem
        self.slow_connect = slow_connect

    def Enable(self):
        self.modem.Enable(True)

    def Disable(self):
        self.modem.Enable(False)

    def Connect(self, simple_connect_props):
        logging.debug('Connecting with properties: %r' % simple_connect_props)
        self.modem.Connect(simple_connect_props)
        if self.slow_connect:
            time.sleep(SLOW_CONNECT_WAIT_SECONDS)

    def Disconnect(self):
        """
        Disconnect Modem.

        Returns:
            True - to indicate that shill may autoconnect again.
        """
        try:
            self.modem.Disconnect()
        except dbus.DBusException as e:
            if (e.get_dbus_name() !=
                    'org.chromium.ModemManager.Error.OperationInitiated'):
                raise e
        return True

    def __str__(self):
        return 'Modem Commands'


class DeviceCommands():
    """Control the modem using shill device interfaces."""
    def __init__(self, shill, device, slow_connect):
        self.shill = shill
        self.device = device
        self.slow_connect = slow_connect
        self.service = None

    def GetService(self):
        service = self.shill.find_cellular_service_object()
        if not service:
            raise error.TestFail(
                'Service failed to appear when using device commands.')
        return service

    def Enable(self):
        self.device.Enable(timeout=DEVICE_TIMEOUT)

    def Disable(self):
        self.service = None
        self.device.Disable(timeout=DEVICE_TIMEOUT)

    def Connect(self, **kwargs):
        self.GetService().Connect()
        if self.slow_connect:
            time.sleep(SLOW_CONNECT_WAIT_SECONDS)

    def Disconnect(self):
        """
        Disconnect Modem.

        Returns:
            False - to indicate that shill may not autoconnect again.
        """
        self.GetService().Disconnect()
        return False

    def __str__(self):
        return 'Device Commands'


class MixedRandomCommands():
    """Control the modem using a mixture of commands on device, modems, etc."""
    def __init__(self, commands_list):
        self.commands_list = commands_list

    def PickRandomCommands(self):
        return self.commands_list[random.randrange(len(self.commands_list))]

    def Enable(self):
        cmds = self.PickRandomCommands()
        logging.info('Enable with %s' % cmds)
        cmds.Enable()

    def Disable(self):
        cmds = self.PickRandomCommands()
        logging.info('Disable with %s' % cmds)
        cmds.Disable()

    def Connect(self, **kwargs):
        cmds = self.PickRandomCommands()
        logging.info('Connect with %s' % cmds)
        cmds.Connect(**kwargs)

    def Disconnect(self):
        cmds = self.PickRandomCommands()
        logging.info('Disconnect with %s' % cmds)
        return cmds.Disconnect()

    def __str__(self):
        return 'Mixed Commands'


class cellular_ModemControl(test.test):
    version = 1

    def CompareModemPowerState(self, modem, expected_state):
        """Compare modem manager power state of a modem to an expected state."""
        return modem.IsEnabled() == expected_state

    def CompareDevicePowerState(self, device, expected_state):
        """Compare the shill device power state to an expected state."""
        state = self.test_env.shill.get_dbus_property(
                device, shill_proxy.ShillProxy.DEVICE_PROPERTY_POWERED)
        logging.info('Device Enabled = %s' % state)
        return state == expected_state

    def CompareServiceState(self, service, expected_states):
        """Compare the shill service state to a set of expected states."""
        if not service:
            logging.info('Service not found.')
            return False

        state = self.test_env.shill.get_dbus_property(
                service, shill_proxy.ShillProxy.SERVICE_PROPERTY_STATE)
        logging.info('Service State = %s' % state)
        return state in expected_states

    def EnsureNotConnectingOrDisconnecting(self):
        """
        Ensure modem is not connecting or disconnecting.

        Raises:
            error.TestFail if it timed out waiting for the modem to finish
            connecting or disconnecting.
        """
        # Shill retries a failed connect attempt with a different APN so
        # check a few times to ensure the modem is not in between connect
        # attempts.
        for _ in range(NUM_MODEM_STATE_CHECKS):
            utils.poll_for_condition(
                lambda: not self.test_env.modem.IsConnectingOrDisconnecting(),
                error.TestFail('Timed out waiting for modem to finish ' +
                               'connecting or disconnecting.'),
                timeout=SERVICE_TIMEOUT)
            time.sleep(MODEM_STATE_CHECK_PERIOD_SECONDS)

    def EnsureDisabled(self):
        """
        Ensure modem disabled, device powered off, and no service.

        Raises:
            error.TestFail if the states are not consistent.
        """
        utils.poll_for_condition(
            lambda: self.CompareModemPowerState(self.test_env.modem, False),
            error.TestFail('Modem failed to enter state Disabled.'))
        utils.poll_for_condition(
            lambda: self.CompareDevicePowerState(self.device, False),
            error.TestFail('Device failed to enter state Powered=False.'))
        utils.poll_for_condition(
            lambda: not self.test_env.shill.find_cellular_service_object(),
            error.TestFail('Service should not be available.'),
            timeout=SERVICE_TIMEOUT)

    def EnsureEnabled(self, check_idle):
        """
        Ensure modem enabled, device powered and service exists.

        Args:
            check_idle: if True, then ensure that the service is idle
                        (i.e. not connected) otherwise ignore the
                        service state

        Raises:
            error.TestFail if the states are not consistent.
        """
        utils.poll_for_condition(
            lambda: self.CompareModemPowerState(self.test_env.modem, True),
            error.TestFail('Modem failed to enter state Enabled'))
        utils.poll_for_condition(
            lambda: self.CompareDevicePowerState(self.device, True),
            error.TestFail('Device failed to enter state Powered=True.'),
            timeout=30)

        service = self.test_env.shill.wait_for_cellular_service_object()
        if check_idle:
            utils.poll_for_condition(
                lambda: self.CompareServiceState(service, ['idle']),
                error.TestFail('Service failed to enter idle state.'),
                timeout=SERVICE_TIMEOUT)

    def EnsureConnected(self):
        """
        Ensure modem connected, device powered on, service connected.

        Raises:
            error.TestFail if the states are not consistent.
        """
        self.EnsureEnabled(check_idle=False)
        utils.poll_for_condition(
            lambda: self.CompareServiceState(
                    self.test_env.shill.find_cellular_service_object(),
                    ['ready', 'portal', 'online']),
            error.TestFail('Service failed to connect.'),
            timeout=SERVICE_TIMEOUT)


    def TestCommands(self, commands):
        """
        Manipulate the modem using modem, device or technology commands.

        Changes the state of the modem in various ways including
        disable while connected and then verifies the state of the
        modem manager and shill.

        Raises:
            error.TestFail if the states are not consistent.

        """
        logging.info('Testing using %s' % commands)

        logging.info('Enabling')
        commands.Enable()
        self.EnsureEnabled(check_idle=not self.autoconnect)

        technology_family = self.test_env.modem.GetCurrentTechnologyFamily()
        if technology_family == cellular.TechnologyFamily.CDMA:
            simple_connect_props = {'number': r'#777'}
        else:
            simple_connect_props = {'number': r'#777', 'apn': self.FindAPN()}

        # Icera modems behave weirdly if we cancel the operation while the
        # modem is connecting. Work around the issue by waiting until the
        # connect operation completes.
        # TODO(benchan): Remove this workaround once the issue is addressed
        # on the modem side.
        self.EnsureNotConnectingOrDisconnecting()

        logging.info('Disabling')
        commands.Disable()
        self.EnsureDisabled()

        logging.info('Enabling again')
        commands.Enable()
        self.EnsureEnabled(check_idle=not self.autoconnect)

        if not self.autoconnect:
            logging.info('Connecting')
            commands.Connect(simple_connect_props=simple_connect_props)
        else:
            logging.info('Expecting AutoConnect to connect')
        self.EnsureConnected()

        logging.info('Disconnecting')
        will_autoreconnect = commands.Disconnect()

        if not (self.autoconnect and will_autoreconnect):
            # Icera modems behave weirdly if we cancel the operation while the
            # modem is disconnecting. Work around the issue by waiting until
            # the disconnect operation completes.
            # TODO(benchan): Remove this workaround once the issue is addressed
            # on the modem side.
            self.EnsureNotConnectingOrDisconnecting()

            self.EnsureEnabled(check_idle=True)
            logging.info('Connecting manually, since AutoConnect was on')
            commands.Connect(simple_connect_props=simple_connect_props)
        self.EnsureConnected()

        logging.info('Disabling')
        commands.Disable()
        self.EnsureDisabled()

    def FindAPN(self):
        default = 'None'
        service = self.test_env.shill.find_cellular_service_object()
        last_good_apn = self.test_env.shill.get_dbus_property(
                service,
                cellular_proxy.CellularProxy.SERVICE_PROPERTY_LAST_GOOD_APN)
        if not last_good_apn:
            return default
        return last_good_apn.get(
                cellular_proxy.CellularProxy.APN_INFO_PROPERTY_APN, default)

    def run_once(self, test_env, autoconnect, mixed_iterations=2,
                 slow_connect=False):
        self.test_env = test_env
        self.autoconnect = autoconnect

        with test_env:
            self.device = self.test_env.shill.find_cellular_device_object()

            modem_commands = ModemCommands(self.test_env.modem,
                                           slow_connect)
            technology_commands = TechnologyCommands(self.test_env.shill,
                                                     modem_commands)
            device_commands = DeviceCommands(self.test_env.shill,
                                             self.device,
                                             slow_connect)

            # shill disables autoconnect on any cellular service before a user
            # logs in (CL:851267). To test the autoconnect scenario, we need a
            # user session to run the test.
            chrome_context = chrome.Chrome()

            # Set up the autoconnect context after starting a user session so
            # that we ensure the autoconnect property is set on the cellular
            # service that may be in the user profile.
            autoconnect_context = shill_context.ServiceAutoConnectContext(
                    self.test_env.shill.wait_for_cellular_service_object,
                    self.autoconnect)

            with contextlib.nested(chrome_context, autoconnect_context):
                # Start with cellular disabled.
                self.test_env.shill.manager.DisableTechnology(
                        shill_proxy.ShillProxy.TECHNOLOGY_CELLULAR)
                self.EnsureDisabled()

                # Run the device commands test first to make sure we have
                # a valid APN needed to connect using the modem commands.
                self.TestCommands(device_commands)
                self.TestCommands(technology_commands)
                self.TestCommands(modem_commands)

                # Run several times using commands mixed from each type
                mixed = MixedRandomCommands([modem_commands,
                                             technology_commands,
                                             device_commands])
                for _ in range(mixed_iterations):
                    self.TestCommands(mixed)

                # Ensure cellular is re-enabled in order to restore AutoConnect
                # settings when ServiceAutoConnectContext exits.
                # TODO(benchan): Refactor this logic into
                # ServiceAutoConnectContext and update other users of
                # ServiceAutoConnectContext.
                self.test_env.shill.manager.EnableTechnology(
                        shill_proxy.ShillProxy.TECHNOLOGY_CELLULAR)
                self.EnsureEnabled(check_idle=False)
