import urllib

from roscraco.response import WirelessSettings
from base import TplinkBase, _extract_js_array_data


class Tplink_WR740N(TplinkBase):

    def confirm_identity(self):
        self._ensure_www_auth_header('Basic realm="TP-LINK Wireless Lite N Router WR740N"')

    def get_wireless_settings(self):
        html_settings = self._make_http_request_read('WlanNetworkRpm.htm')
        html_security = self._make_http_request_read('WlanSecurityRpm.htm')
        return _parse_wireless_settings(html_settings, html_security)

    def push_wireless_settings(self, settings):
        get_params_settings = _generate_wireless_settings_data(settings)
        self._make_http_request_write('WlanNetworkRpm.htm?%s' % urllib.urlencode(get_params_settings))

        get_params_security = _generate_wireless_security_data(settings)
        self._make_http_request_write('WlanSecurityRpm.htm?%s' % urllib.urlencode(get_params_security))

        return self.get_wireless_settings() == settings


def _parse_wireless_settings(html_settings, html_security):
    """Extracts the Wireless settings from the page contents
    for a WR740N (and some other models)."""
    obj = WirelessSettings()
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WEP64)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WEP128)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WPA)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WPA2)

    settings_array = _extract_js_array_data(html_settings, 'wlanPara')
    obj.set_ssid(settings_array[3])
    obj.set_enabled_status(settings_array[8] == 1)
    obj.set_ssid_broadcast_status(settings_array[9] == 1)
    obj.set_channel(settings_array[10])
    obj.set_internal_param('region', settings_array[5])
    obj.set_internal_param('mode', settings_array[7])
    obj.set_internal_param('chanWidth', settings_array[11])
    obj.set_internal_param('rate', settings_array[12])

    security_array = _extract_js_array_data(html_security, 'wlanPara')
    wlan_list_array = _extract_js_array_data(html_security, 'wlanList')

    security_type = int(security_array[2])

    if security_type == 1: # WEP of some sort
        bit_length = int(wlan_list_array[1])
        if bit_length == 13: # 128 bit length
            security_type = WirelessSettings.SECURITY_TYPE_WEP128
        else:
            security_type = WirelessSettings.SECURITY_TYPE_WEP64
    elif security_type == 3: # WPA-PSK (WPA or WPA2)
        # string like '331', '332', '333'
        # we're interested in the 3rd char, which deals with WPA-PSK/WPA2-PSK
        # 3rd char possible values {1: WPA, 2: WPA2, 3: Automatic (WPA + WPA2)}
        security_options = security_array[3]

        if int(security_options[2]) == 1:
            security_type = WirelessSettings.SECURITY_TYPE_WPA
        else:
            security_type = WirelessSettings.SECURITY_TYPE_WPA2
    else: # type is either 0 (no security) or 2 (WPA-Enterprise)
        security_type = WirelessSettings.SECURITY_TYPE_NONE

    obj.set_security_type(security_type)

    password = wlan_list_array[0] if obj.security_type_is_wep else security_array[9]
    obj.set_password(password)

    return obj


def _generate_wireless_security_data(settings):
    """Generates a wireless security data array to push to the
    router from the given wireless settings.

    Keep in mind that the settings array generated by this is resetting some fields
    that it doesn't support/care about (like radius settings, etc.).
    """
    WirelessSettings = settings.__class__

    settings.ensure_valid()

    data = {}
    data['wepSecOpt'] = 3 # WEP Type = Automatic
    data['wpaSecOpt'] = 3 # WPA-Enterprise Type = Automatic
    data['pskSecOpt'] = 1 if settings.security_type == WirelessSettings.SECURITY_TYPE_WPA else 2 # 1 = WPA, 2 = WPA2
    data['pskCipher'] = 1 # WPA-PSK/WPA2-PSK encryption method (1: Automatic, 2: TKIP, 3: AES)
    data['wpaCipher'] = 1 # WPA-Enterprise encryption method (1: Automatic)
    data['pskSecret'] = '' # default value for a WPA-PSK/WPA2-PSK password
    data['keytype'] = 2 # 1 is for HEX WEP, 2 is for ASCII WEP password
    data['keynum'] = 1 # which of the 4 WEP keys to use (if WEP is enabled)

    # These are the 4 WEP keys and their lengths.. empty by default - to be filled later if needed
    # only one of these keys is actively used (specified by `keynum` above)
    merge_with =  {'key1': '', 'key2': '', 'key3': '', 'key4': '', 'length1': 0, 'length2': 0, 'length3': 0, 'length4': 0}
    data = dict(data, **merge_with)

    # Some more WPA-Enterprise settings (we're not using those at all)
    merge_with = {'radiusIp': '', 'radiusPort': 1812, 'radiusSecret': ''}
    data = dict(data, **merge_with)

    # WPA and WPA-PSK intervals and Save button field
    merge_with = {'intervalWpa': 0, 'interval': 0, 'Save': 'Save'}
    data = dict(data, **merge_with)


    if settings.security_type_is_wep:
        data['secType'] = 1
    elif settings.security_type in (WirelessSettings.SECURITY_TYPE_WPA, WirelessSettings.SECURITY_TYPE_WPA2):
        data['secType'] = 3
    else:
        data['secType'] = 0


    if settings.security_type_is_wep:
        # 64bit = 5, 128bit = 13
        bit_length = 5 if settings.security_type == WirelessSettings.SECURITY_TYPE_WEP64 else 13

        data['key1'] = settings.password
        data['length1'] = bit_length
        data['keytype'] = 1 if settings.is_wep_password_in_hex else 2 # ASCII or HEX
    elif settings.security_type != WirelessSettings.SECURITY_TYPE_NONE:
        data['pskSecret'] = settings.password


    return data


def _generate_wireless_settings_data(settings):
    """Generates a wireless settings data array to push to the
    router from the given wireless settings."""
    settings.ensure_valid()

    data = {'ssid1': settings.ssid, 'channel': settings.channel, 'Save': 'Save'}

    if settings.is_enabled:
        data['ap'] = 1

    if settings.is_broadcasting_ssid:
        data['broadcast'] = 2

    # preserve some of the params we don't handle
    for k in ('region', 'mode', 'chanWidth', 'rate'):
        data[k] = settings.get_internal_param(k)

    # WDS (WLAN bridging) related settings
    # we'll clear them all by default
    merge_with = {'brlssid': '', 'brlbssid': '', 'keytype': 1, 'wepindex'
                    'authtype': 1, 'keytext': ''}
    data = dict(data, **merge_with)

    return data
