# Copyright 2018 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 logging
from collections import namedtuple

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.networking.chrome_testing \
        import chrome_networking_test_context as cntc
from autotest_lib.client.cros.networking.chrome_testing \
        import chrome_networking_test_api as cnta


class ChromeEnterpriseNetworkContext(object):
    """
    This class contains all the Network API methods required for
    Enterprise Network WiFi tests.

    """
    SHORT_TIMEOUT = 20
    LONG_TIMEOUT = 120


    def __init__(self, browser_instance):
        self.browser = browser_instance
        testing_context = cntc.ChromeNetworkingTestContext(browser=self.browser)
        testing_context.setup()
        self.chrome_net_context = cnta.ChromeNetworkProvider(testing_context)
        self.enable_wifi_on_dut()


    def _extract_wifi_network_info(self, networks_found_list):
        """
        Extract the required Network params from list of Networks found.

        Filter out the required network parameters such Network Name/SSID,
        GUID, connection state and security type of each of the networks in
        WiFi range of the DUT.

        @param networks_found_list: Network information returned as a result
                of the getVisibleNetworks api.

        @returns: Formatted list of namedtuples containing the
                required network parameters.

        """
        network_info_list = []
        network_info = namedtuple(
                'NetworkInfo', 'name guid connectionState security')

        for network in networks_found_list:
            network_data = network_info(
                                name=network['Name'],
                                guid=network['GUID'],
                                connectionState=network['ConnectionState'],
                                security=network['WiFi']['Security'])
            network_info_list.append(network_data)
        return network_info_list


    def _get_network_info(self, ssid):
        """
        Returns the Network parameters for a specific network.

        @param ssid: SSID of the network.

        @returns: The NetworkInfo tuple containing the network parameters.
                Returns None if network info for the SSID was not found.

        """
        networks_in_range = self._extract_wifi_network_info(
                self.chrome_net_context.get_wifi_networks())
        logging.debug('Network info of all the networks in WiFi'
                'range of DUT:%r', networks_in_range)
        for network_info in networks_in_range:
            if network_info.name == ssid:
                return network_info
        return None


    def _get_network_connection_state(self, ssid):
        """
        Returns the connection State of the network.

        @returns: Connection State for the SSID.

        """
        network_info = self._get_network_info(ssid)
        return network_info.connectionState


    def connect_to_network(self, ssid):
        """
        Triggers a manual connect to the network using networkingPrivate API.

        @param ssid: The ssid that the connection request is initiated for.

        @raises error.TestFail: If the WiFi network is not in WiFi range of the
                DUT or if the DUT cannot manually connect to the SSID.

        """
        if not self.is_network_in_range(ssid):
            raise error.TestFail("The SSID: %r is not in WiFi range of the DUT"%
                ssid)

        network_to_connect = self._get_network_info(ssid)
        logging.info("Triggering a manual connect to network SSID: %r, GUID %r",
                network_to_connect.name, network_to_connect.guid)

        # TODO(krishnargv): Replace below code with the
        # self.chrome_net_context.connect_to_network(network_to_connect) method.
        new_network_connect = self.chrome_net_context._chrome_testing.\
                call_test_function(
                self.LONG_TIMEOUT,
                'connectToNetwork',
                '"%s"'% network_to_connect.guid)
        logging.debug("Manual network connection status: %r",
                new_network_connect['status'])
        if (new_network_connect['status'] ==
                'chrome-test-call-status-failure'):
            raise error.TestFail(
                    'Could not connect to %s network. Error returned by '
                    'chrome.networkingPrivate.startConnect API: %s' %
                    (network_to_connect.name, new_network_connect['error']))


    def disconnect_from_network(self, ssid):
        """
        Triggers a disconnect from the network using networkingPrivate API.

        @param ssid: The ssid that the disconnection request is initiated for.

        @raises error.TestFail: If the WiFi network is not in WiFi range of the
                DUT or if the DUT cannot manually disconnect from the SSID.

        """
        if not self.is_network_in_range(ssid):
            raise error.TestFail("The SSID: %r is not in WiFi range of the DUT"%
                ssid)

        network_to_disconnect = self._get_network_info(ssid)
        logging.info("Triggering a disconnect from network SSID: %r, GUID %r",
                network_to_disconnect.name, network_to_disconnect.guid)

        new_network_disconnect = self.chrome_net_context._chrome_testing.\
                call_test_function(
                self.LONG_TIMEOUT,
                'disconnectFromNetwork',
                '"%s"'% network_to_disconnect.guid)
        logging.debug("Manual network disconnection status: %r",
                new_network_disconnect['status'])
        if (new_network_disconnect['status'] ==
                'chrome-test-call-status-failure'):
            raise error.TestFail(
                    'Could not disconnect from %s network. Error returned by '
                    'chrome.networkingPrivate.startDisconnect API: %s' %
                    (network_to_disconnect.name,
                    new_network_disconnect['error']))


    def enable_wifi_on_dut(self):
        """Enable the WiFi interface on the DUT if it is disabled."""
        enabled_devices = self.chrome_net_context.get_enabled_devices()
        if (self.chrome_net_context.WIFI_DEVICE not in enabled_devices):
            self.chrome_net_context.enable_network_device(
                self.chrome_net_context.WIFI_DEVICE)


    def is_network_in_range(self, ssid):
        """
        Returns True if the WiFi network is within WiFi range of the DUT.

        @param ssid: The SSID of the network.

        @returns: True if the network/ssid is within WiFi range of the DUT,
                else returns False

        """
        return self._get_network_info(ssid) is not None


    def is_network_connected(self, ssid):
        """
        Return True if the DUT is connected to the Network.

        Returns True if the DUT is connected to the network. Waits for a
        a short time if the DUT is in a connecting state.

        @param ssid: The SSID of the network.

        @returns: True if the DUT is connected to the network/ssid,
                else returns False

        @raises error.TestFail: If the DUT is stuck in the connecting state.

        """
        utils.poll_for_condition(
                lambda:self._get_network_connection_state(ssid) != 'Connecting',
                exception=error.TestFail('Device stuck in connecting state'),
                timeout=self.SHORT_TIMEOUT)
        network_connection_state = self._get_network_connection_state(ssid)
        if network_connection_state is None:
            return False
        logging.debug("Connection state for SSID-%r is: %r",
                ssid, network_connection_state)
        return network_connection_state == 'Connected'