
# this package
from apcommand.baseclass import BaseClass
from iwlist import IwlistCommand
from iwconfig import IwconfigCommand


class SettingsValidator(BaseClass):
    """
    A validator for the settings
    """
    def __init__(self, connection, interface, antennae=2):
        """
        SettingsValidator constructor

        :param:

         - `connection`: connection to the device to validate
         - `interface`: network interface to check (e.g. wlan0)
         - `antennae`: number of antennae (spatial streams)
        """
        super(SettingsValidator, self).__init__()
        self.connection = connection
        self.interface = interface
        self._iwlist = None
        self._iwconfig = None
        self._bitrates = None
        return

    @property
    def bitrates(self):
        """
        a map of channel to bitrate
        """
        if self._bitrates is None:
            g_channels = [str(ch) for ch in range(1,12)]
            a_lower_channels = '36 44 149 157'.split()
            a_upper_channels = "40 48 153 161".split()
            a_channels = a_lower_channels + a_upper_channels
            g_rates = ['120 Mb/s' for g in g_channels]
            a_rates = ['300 Mb/s' for a in a_channels]
            channel_rate = dict(zip(g_channels + a_channel,
                                    g_rates + a_rates))
            self._bitrates = {2:channel_rate}
        return self._bitrates

    @property
    def iwlist(self):
        """
        IwlistCommand        
        """
        if self._iwlist is None:
            self._iwlist = IwlistCommand(connection=self.connection,
                                         interface=self.interface)
        return self._iwlist

    @property
    def iwconfig(self):
        """
        IwconfigCommand
        """
        if self._iwconfig is None:
            self._iwconfig = IwconfigCommand(connection=self.connection,
                                             interface=self.interface)
        return self._iwconfig

    def channel(self, channel):
        """
        Checks iwlist for the channel

        :param:

         - `channel`: wifi channel (e.g. '6')

        :raises: RuntimeError if channel settings are wrong
        """
        actual_channel = self.iwlist.channel
        if actual_channel != channel:
            raise RuntimeError("Expected channel: {0}, Actual: {1}".format(channel,
                                                                           actual_channel))
        actual_rate = self.iwconfig.bitrate
        return 



# python standard library
import unittest

#third-party
from mock import MagicMock

# this package
from iwconfig import sample_output as iwconfig_sample
from iwlist import sample_output as iwlist_sample
from iwlist import SAMPLE_CHANNEL as IWLIST_CHANNEL
from apcommand.connections.nonlocalconnection import OutputError


FIVE_GHZ_CHANNEL="""
iwlist ath0 channel
ath0      70 channels in total; available frequencies :
          Channel 36 : 5.18 GHz
          Channel 40 : 5.2 GHz
          Channel 44 : 5.22 GHz
          Channel 48 : 5.24 GHz
          Channel 52 : 5.26 GHz
          Channel 56 : 5.28 GHz
          Channel 60 : 5.3 GHz
          Channel 64 : 5.32 GHz
          Channel 100 : 5.5 GHz
          Channel 104 : 5.52 GHz
          Channel 108 : 5.54 GHz
          Channel 112 : 5.56 GHz
          Channel 116 : 5.58 GHz
          Channel 120 : 5.6 GHz
          Channel 124 : 5.62 GHz
          Channel 128 : 5.64 GHz
          Channel 132 : 5.66 GHz
          Channel 136 : 5.68 GHz
          Channel 140 : 5.7 GHz
          Channel 149 : 5.745 GHz
          Channel 153 : 5.765 GHz
          Channel 157 : 5.785 GHz
          Channel 161 : 5.805 GHz
          Channel 165 : 5.825 GHz
          Current Frequency:5.18 GHz (Channel 36)

""".split('\n')


class TestChannel(unittest.TestCase):
    def setUp(self):
        self.connection = MagicMock()
        self.interface = 'ath0'
        self.validator = SettingsValidator(connection=self.connection,
                                           interface=self.interface)
        return

    def setup_sample_output(self):
        output, error = iwconfig_sample, ''
        o_e = OutputError(output, error)
        self.connection.iwconfig.return_value = o_e
        output, error = iwlist_sample, ''
        o_e_2 = OutputError(output, error)
        self.connection.iwlist.return_value = o_e_2
        return

    def test_channel(self):
        self.setup_sample_output()
        self.validator.channel(IWLIST_CHANNEL)
        self.assertRaises(RuntimeError, self.validator.channel, ['99'])

        output, error = FIVE_GHZ_CHANNEL, ''
        o_e = OutputError(output, error)
        self.connection.iwlist.return_value = o_e
        self.assertRaises(RuntimeError, self.validator.channel, IWLIST_CHANNEL)
        return
