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

        Note: if you're using this function to do things like initiating scans,
        consider initating those through Shill instead, to avoid collisions.

        @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)
