# 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 collections
import logging
import re
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes


# Used to represent stations we parse out of scan results.
Station = collections.namedtuple('Station',
                                 ['bssid', 'frequency', 'signal', 'ssid'])

class WpaCliProxy(object):
    """Interacts with a DUT through wpa_cli rather than shill."""

    SCANNING_INTERVAL_SECONDS = 5
    POLLING_INTERVAL_SECONDS = 0.5
    # From wpa_supplicant.c:wpa_supplicant_state_txt()
    WPA_SUPPLICANT_ASSOCIATING_STATES = (
            'AUTHENTICATING',
            'ASSOCIATING',
            'ASSOCIATED',
            '4WAY_HANDSHAKE',
            'GROUP_HANDSHAKE')
    WPA_SUPPLICANT_ASSOCIATED_STATES = (
            'COMPLETED',)
    ANDROID_CMD_FORMAT = '/system/bin/wpa_cli IFNAME={0[ifname]} {0[cmd]}'
    BRILLO_CMD_FORMAT = 'su system /system/bin/wpa_cli -i{0[ifname]} -p/data/misc/wifi/sockets {0[cmd]}'
    CROS_CMD_FORMAT = ('su wpa -s /bin/bash '
                       '-c "/usr/bin/wpa_cli -i {0[ifname]} {0[cmd]}"')
    CAST_CMD_FORMAT = '/system/bin/wpa_cli -i {0[ifname]} {0[cmd]}'


    def __init__(self, host, wifi_if):
        self._host = host
        self._wifi_if = wifi_if
        self._created_networks = {}
        # TODO(wiley) Hardcoding this IFNAME prefix makes some big assumptions.
        #             we'll need to discover this parameter as it becomes more
        #             generally useful.
        if host.get_os_type() == 'android':
            self._wpa_cli_cmd_format = self.ANDROID_CMD_FORMAT
        elif host.get_os_type() == 'brillo':
            self._wpa_cli_cmd_format = self.BRILLO_CMD_FORMAT
        elif host.get_os_type() == 'cros':
            self._wpa_cli_cmd_format = self.CROS_CMD_FORMAT
        elif host.get_os_type() == 'cast_os':
            self._wpa_cli_cmd_format = self.CAST_CMD_FORMAT


    def _add_network(self, ssid):
        """
        Add a wpa_supplicant network for ssid.

        @param ssid string: name of network to add.
        @return int network id of added network.

        """
        add_result = self.run_wpa_cli_cmd('add_network', check_result=False)
        network_id = int(add_result.stdout.splitlines()[-1])
        self.run_wpa_cli_cmd('set_network %d ssid \\"%s\\"' %
                             (network_id, ssid))
        self._created_networks[ssid] = network_id
        logging.debug('Added network %s=%d', ssid, network_id)
        return network_id


    def run_wpa_cli_cmd(self, command, check_result=True):
        """
        Run a wpa_cli command and optionally check the result.

        @param command string: suffix of a command to be prefixed with
                an appropriate wpa_cli for this host.
        @param check_result bool: True iff we want to check that the
                command comes back with an 'OK' response.
        @return result object returned by host.run.

        """
        cmd = self._wpa_cli_cmd_format.format(
                {'ifname' : self._wifi_if, 'cmd' : command})
        result = self._host.run(cmd)
        if check_result and not result.stdout.strip().endswith('OK'):
            raise error.TestFail('wpa_cli command failed: %s' % command)

        return result


    def _get_status_dict(self):
        """
        Gets the status output for a WiFi interface.

        Get the output of wpa_cli status.  This summarizes what wpa_supplicant
        is doing with respect to the WiFi interface.

        Example output:

            Using interface 'wlan0'
            wpa_state=INACTIVE
            p2p_device_address=32:76:6f:f2:a6:c4
            address=30:76:6f:f2:a6:c4

        @return dict of key/value pairs parsed from output using = as divider.

        """
        status_result = self.run_wpa_cli_cmd('status', check_result=False)
        return dict([line.strip().split('=', 1)
                     for line in status_result.stdout.splitlines()
                     if line.find('=') > 0])


    def _is_associating_or_associated(self):
        """@return True if the DUT is assocating or associated with a BSS."""
        state = self._get_status_dict().get('wpa_state', None)
        return state in (self.WPA_SUPPLICANT_ASSOCIATING_STATES +
                         self.WPA_SUPPLICANT_ASSOCIATED_STATES)


    def _is_associated(self, ssid):
        """
        Check if the DUT is associated to a given SSID.

        @param ssid string: SSID of the network we're concerned about.
        @return True if we're associated with the specified SSID.

        """
        status_dict = self._get_status_dict()
        return (status_dict.get('ssid', None) == ssid and
                status_dict.get('wpa_state', None) in
                        self.WPA_SUPPLICANT_ASSOCIATED_STATES)


    def _is_connected(self, ssid):
        """
        Check that we're connected to |ssid| and have an IP address.

        @param ssid string: SSID of the network we're concerned about.
        @return True if we have an IP and we're associated with |ssid|.

        """
        status_dict = self._get_status_dict()
        return (status_dict.get('ssid', None) == ssid and
                status_dict.get('ip_address', None))


    def clean_profiles(self):
        """Remove state associated with past networks we've connected to."""
        # list_networks output looks like:
        # Using interface 'wlan0'^M
        # network id / ssid / bssid / flags^M
        # 0    SimpleConnect_jstja_ch1 any     [DISABLED]^M
        # 1    SimpleConnect_gjji2_ch6 any     [DISABLED]^M
        # 2    SimpleConnect_xe9d1_ch11        any     [DISABLED]^M
        list_networks_result = self.run_wpa_cli_cmd(
                'list_networks', check_result=False)
        start_parsing = False
        for line in list_networks_result.stdout.splitlines():
            if not start_parsing:
                if line.startswith('network id'):
                    start_parsing = True
                continue

            network_id = int(line.split()[0])
            self.run_wpa_cli_cmd('remove_network %d' % network_id)
        self._created_networks = {}


    def create_profile(self, _):
        """
        This is a no op, since we don't have profiles.

        @param _ ignored.

        """
        logging.info('Skipping create_profile on %s', self.__class__.__name__)


    def pop_profile(self, _):
        """
        This is a no op, since we don't have profiles.

        @param _ ignored.

        """
        logging.info('Skipping pop_profile on %s', self.__class__.__name__)


    def push_profile(self, _):
        """
        This is a no op, since we don't have profiles.

        @param _ ignored.

        """
        logging.info('Skipping push_profile on %s', self.__class__.__name__)


    def remove_profile(self, _):
        """
        This is a no op, since we don't have profiles.

        @param _ ignored.

        """
        logging.info('Skipping remove_profile on %s', self.__class__.__name__)


    def init_test_network_state(self):
        """Create a clean slate for tests with respect to remembered networks.

        For wpa_cli hosts, this means removing all remembered networks.

        @return True iff operation succeeded, False otherwise.

        """
        self.clean_profiles()
        return True


    def connect_wifi(self, assoc_params):
        """
        Connect to the WiFi network described by AssociationParameters.

        @param assoc_params AssociationParameters object.
        @return serialized AssociationResult object.

        """
        logging.debug('connect_wifi()')
        # Ouptut should look like:
        #   Using interface 'wlan0'
        #   0
        assoc_result = xmlrpc_datatypes.AssociationResult()
        network_id = self._add_network(assoc_params.ssid)
        if assoc_params.is_hidden:
            self.run_wpa_cli_cmd('set_network %d %s %s' %
                                 (network_id, 'scan_ssid', '1'))

        sec_config = assoc_params.security_config
        for field, value in sec_config.get_wpa_cli_properties().iteritems():
            self.run_wpa_cli_cmd('set_network %d %s %s' %
                                 (network_id, field, value))
        self.run_wpa_cli_cmd('select_network %d' % network_id)

        # Wait for an appropriate BSS to appear in scan results.
        scan_results_pattern = '\t'.join(['([0-9a-f:]{17})', # BSSID
                                          '([0-9]+)',  # Frequency
                                          '(-[0-9]+)',  # Signal level
                                          '(.*)',  # Encryption types
                                          '(.*)'])  # SSID
        last_scan_time = -1.0
        start_time = time.time()
        while time.time() - start_time < assoc_params.discovery_timeout:
            assoc_result.discovery_time = time.time() - start_time
            if self._is_associating_or_associated():
                # Internally, wpa_supplicant writes its scan_results response
                # to a 4kb buffer.  When there are many BSS's, the buffer fills
                # up, and we'll never see the BSS we care about in some cases.
                break

            scan_result = self.run_wpa_cli_cmd('scan_results',
                                               check_result=False)
            found_stations = []
            for line in scan_result.stdout.strip().splitlines():
                match = re.match(scan_results_pattern, line)
                if match is None:
                    continue
                found_stations.append(
                        Station(bssid=match.group(1), frequency=match.group(2),
                                signal=match.group(3), ssid=match.group(5)))
            logging.debug('Found stations: %r',
                          [station.ssid for station in found_stations])
            if [station for station in found_stations
                    if station.ssid == assoc_params.ssid]:
                break

            if time.time() - last_scan_time > self.SCANNING_INTERVAL_SECONDS:
                # Sometimes this might fail with a FAIL-BUSY if the previous
                # scan hasn't finished.
                scan_result = self.run_wpa_cli_cmd('scan', check_result=False)
                if scan_result.stdout.strip().endswith('OK'):
                    last_scan_time = time.time()
            time.sleep(self.POLLING_INTERVAL_SECONDS)
        else:
            assoc_result.failure_reason = 'Discovery timed out'
            return assoc_result.serialize()

        # Wait on association to finish.
        start_time = time.time()
        success = utils.poll_for_condition(
                condition=lambda: self._is_associated(assoc_params.ssid),
                timeout=assoc_params.association_timeout,
                sleep_interval=self.POLLING_INTERVAL_SECONDS,
                desc='Wait on association to finish')
        assoc_result.association_time = time.time() - start_time
        if not success:
            assoc_result.failure_reason = 'Association timed out'
            return assoc_result.serialize()

        # Then wait for ip configuration to finish.
        start_time = time.time()
        success = utils.poll_for_condition(
                condition=lambda: self._is_connected(assoc_params.ssid),
                timeout=assoc_params.configuration_timeout,
                sleep_interval=self.POLLING_INTERVAL_SECONDS,
                desc='Wait for ip configuration to finish')
        assoc_result.configuration_time = time.time() - start_time
        if not success:
            assoc_result.failure_reason = 'DHCP negotiation timed out'
            return assoc_result.serialize()

        assoc_result.success = True
        logging.info('Connected to %s', assoc_params.ssid)
        return assoc_result.serialize()


    def disconnect(self, ssid):
        """
        Disconnect from a WiFi network named |ssid|.

        @param ssid string: name of network to disable in wpa_supplicant.

        """
        logging.debug('disconnect()')
        if ssid not in self._created_networks:
            return False
        self.run_wpa_cli_cmd('disable_network %d' %
                             self._created_networks[ssid])
        return True


    def delete_entries_for_ssid(self, ssid):
        """Delete a profile entry.

        @param ssid string of WiFi service for which to delete entries.
        @return True on success, False otherwise.
        """
        return self.disconnect(ssid)


    def set_device_enabled(self, wifi_interface, enabled):
        """Enable or disable the WiFi device.

        @param wifi_interface: string name of interface being modified.
        @param enabled: boolean; true if this device should be enabled,
                false if this device should be disabled.
        @return True if it worked; false, otherwise

        """
        return False


    def sync_time_to(self, epoch_seconds):
        """
        Sync time on the DUT to |epoch_seconds| from the epoch.

        @param epoch_seconds float: number of seconds since the epoch.

        """
        # This will claim to fail, but will work anyway.
        self._host.run('date -u %f' % epoch_seconds, ignore_status=True)
