# Copyright 2014 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
import socket

from autotest_lib.client.common_lib import error

# See server/cros/network/wifi_test_context_manager.py for commandline
# flags to control IP addresses in WiFi tests.
DEFAULT_FAILURE_MESSAGE = (
        'Cannot infer DNS name of companion device from an IP address.')
ATTENUATOR_FAILURE_MESSAGE = (
        'Cannot infer DNS name of WiFi variable attenuator from a client IP '
        'address.  Use --atten_addr=<ip or dns name>')
BLUETOOTH_TESTER_FAILURE_MESSAGE = (
        'Remote host cannot be an IP address unless tester specified with '
         '--args tester=IP')
ROUTER_FAILURE_MESSAGE = (
        'Cannot infer DNS name of WiFi router from a client IP address.')
PCAP_FAILURE_MESSAGE = (
        'Cannot infer DNS name of Packet Capturer from a client IP address.')


def is_ip_address(hostname):
    """Infers whether |hostname| could be an IP address.

    @param hostname: string DNS name or IP address.
    @return True iff hostname is a valid IP address.

    """
    try:
        socket.inet_aton(hostname)
        return True
    except socket.error:
        return False


def get_companion_device_addr(client_hostname,
                              suffix,
                              cmdline_override=None,
                              not_dnsname_msg=DEFAULT_FAILURE_MESSAGE,
                              allow_failure=False):
    """Build a usable hostname for a test companion device from the client name.

    Optionally, override the generated name with a commandline provided version.

    @param client_hostname: string DNS name of device under test (the client).
    @param suffix: string suffix to append to the client hostname.
    @param cmdline_override: optional DNS name of companion device.  If this is
            given, it overrides the generated client based hostname.
    @param not_dnsname_msg: string message to include in the exception raised
            if the client hostname is found to be an IP address rather than a
            DNS name.
    @param allow_failure: boolean True iff we should return None on failure to
            infer a DNS name.
    @return string DNS name of companion device or None if |allow_failure|
            is True and no DNS name can be inferred.

    """
    if cmdline_override is not None:
        return cmdline_override
    if is_ip_address(client_hostname):
        logging.error('%r looks like an IP address?', client_hostname)
        if allow_failure:
            return None
        raise error.TestError(not_dnsname_msg)
    parts = client_hostname.split('.', 1)
    parts[0] = parts[0] + suffix
    return '.'.join(parts)


def get_router_addr(client_hostname, cmdline_override=None):
    """Build a hostname for a WiFi router from the client hostname.

    Optionally override that hostname with the provided command line hostname.

    @param client_hostname: string DNS name of the client.
    @param cmdline_override: string DNS name of the router provided
            via commandline arguments.
    @return usable DNS name for router host.

    """
    return get_companion_device_addr(
            client_hostname,
            '-router',
            cmdline_override=cmdline_override,
            not_dnsname_msg=ROUTER_FAILURE_MESSAGE)


def get_pcap_addr(client_hostname,
                  cmdline_override=None,
                  allow_failure=False):
    """Build a hostname for a packet capturer from the client hostname.

    @param client_hostname: string DNS name of the client.
    @param cmdline_override: string DNS name of the packet capturer provided
            via commandline arguments.
    @return usable DNS name for capturer host or None.

    """
    return get_companion_device_addr(
            client_hostname,
            '-pcap',
            not_dnsname_msg=PCAP_FAILURE_MESSAGE,
            allow_failure=allow_failure)


def get_attenuator_addr(client_hostname,
                        cmdline_override=None,
                        allow_failure=False):
    """Build a hostname for a WiFi variable attenuator from the client hostname.

    Optionally override that hostname with the provided command line hostname.

    @param client_hostname: string DNS name of the client.
    @param cmdline_override: string DNS name of the variable attenuator
            controller provided via commandline arguments.
    @param allow_failure: boolean True iff we should return None on failure to
            infer a DNS name.
    @return usable DNS name for attenuator controller.

    """
    return get_companion_device_addr(
            client_hostname,
            '-attenuator',
            cmdline_override=cmdline_override,
            not_dnsname_msg=ATTENUATOR_FAILURE_MESSAGE,
            allow_failure=allow_failure)


def get_tester_addr(client_hostname, cmdline_override=None):
    """Build a hostname for a Bluetooth test device from the client hostname.

    Optionally override that hostname with the provided command line hostname.

    @param client_hostname: string DNS name of the client.
    @param cmdline_override: string DNS name of the Bluetooth tester
            provided via commandline arguments.
    @return usable DNS name for Bluetooth tester device.

    """
    return get_companion_device_addr(
            client_hostname,
            '-router',
            cmdline_override=cmdline_override,
            not_dnsname_msg=BLUETOOTH_TESTER_FAILURE_MESSAGE)
