"""Utils for API usage"""
import logging

from flask import make_response
from flask.ext.restful import Api

import re
from netaddr import IPAddress
import simplejson as json

from compass.api import app

api = Api(app)


def make_json_response(status_code, data):
    """Wrap json format to the reponse object"""

    result = json.dumps(data, indent=4)
    resp = make_response(result, status_code)
    resp.headers['Content-type'] = 'application/json'
    return resp


def add_resource(*args, **kwargs):
    """Add resource"""
    api.add_resource(*args, **kwargs)


def is_valid_ip(ip_address):
    """Valid the format of an Ip address"""
    if not ip_address:
        return False

    regex = ('^(([0-9]|[1-9][0-9]|1[0-9]{2}|[1-2][0-4][0-9]|25[0-5])\.)'
             '{3}'
             '([0-9]|[1-9][0-9]|1[0-9]{2}|[1-2][0-4][0-9]|25[0-5])')

    if re.match(regex, ip_address):
        return True

    return False


def is_valid_ipnetowrk(ip_network):
    """Valid the format of an Ip network"""

    if not ip_network:
        return False

    regex = ('^(([0-9]|[1-9][0-9]|1[0-9]{2}|[1-2][0-4][0-9]|25[0-5])\.)'
             '{3}'
             '([0-9]|[1-9][0-9]|1[0-9]{2}|[1-2][0-4][0-9]|25[0-5])'
             '((\/[0-9]|\/[1-2][0-9]|\/[1-3][0-2]))$')

    if re.match(regex, ip_network):
        return True
    return False


def is_valid_netmask(ip_addr):
    """Valid the format of a netmask"""
    try:
        ip_address = IPAddress(ip_addr)
        return ip_address.is_netmask()

    except Exception:
        return False


def is_valid_gateway(ip_addr):
    """Valid the format of gateway"""

    invalid_ip_prefix = ['0', '224', '169', '127']
    try:
        # Check if ip_addr is an IP address and not start with 0
        ip_addr_prefix = ip_addr.split('.')[0]
        if is_valid_ip(ip_addr) and ip_addr_prefix not in invalid_ip_prefix:
            ip_address = IPAddress(ip_addr)
            if not ip_address.is_multicast():
                # Check if ip_addr is not multicast and reserved IP
                return True
        return False
    except Exception:
        return False


def is_valid_security_config(config):
    """Valid the format of security section in config"""

    security_keys = ['server_credentials', 'service_credentials',
                     'console_credentials']
    fields = ['username', 'password']
    logging.debug('config: %s', config)
    for key in security_keys:
        try:
            content = config[key]
        except KeyError:
            error_msg = "Missing '%s' in security config!" % key
            logging.error(error_msg)
            raise KeyError(error_msg)

        for k in fields:
            try:
                value = content[k]
                if not value:
                    return False, '%s in %s cannot be null!' % (k, key)

            except KeyError:
                error_msg = ("Missing '%s' in '%s' section of security config"
                             % (k, key))
                logging.error(error_msg)
                raise KeyError(error_msg)

    return True, 'valid!'


def is_valid_networking_config(config):
    """Valid the format of networking config"""

    networking = ['interfaces', 'global']

    def _is_valid_interfaces_config(interfaces_config):
        """Valid the format of interfaces section in config"""

        expected_keys = ['management', 'tenant', 'public', 'storage']
        required_fields = ['nic', 'promisc']
        normal_fields = ['ip_start', 'ip_end', 'netmask']
        other_fields = ['gateway', 'vlan']

        interfaces_keys = interfaces_config.keys()
        for key in expected_keys:
            if key not in interfaces_keys:
                error_msg = "Missing '%s' in interfaces config!" % key
                return False, error_msg

            content = interfaces_config[key]
            for field in required_fields:
                if field not in content:
                    error_msg = "Keyword '%s' in interface %s cannot be None!"\
                                % (field, key)
                    return False, error_msg

                value = content[field]
                if value is None:
                    error_msg = ("The value of '%s' in '%s' "
                                 'config cannot be None!' %
                                 (field, key))
                    return False, error_msg

                if field == 'promisc':
                    valid_values = [0, 1]
                    if int(value) not in valid_values:
                        return (
                            False,
                            ('The value of Promisc for interface %s can '
                             'only be 0/1.bit_length' % key)
                            )

                elif field == 'nic':
                    if not value.startswith('eth'):
                        return (
                            False,
                            ('The value of nic for interface %s should start'
                             'with eth' % key)
                            )

            if not content['promisc']:
                for field in normal_fields:
                    value = content[field]
                    if field == 'netmask' and not is_valid_netmask(value):
                        return (False, "Invalid netmask format for interface "
                                " %s: '%s'!" % (key, value))
                    elif not is_valid_ip(value):
                        return (False,
                                "Invalid Ip format for interface %s: '%s'"
                                % (key, value))

            for field in other_fields:
                if field in content and field == 'gateway':
                    value = content[field]
                    if value and not is_valid_gateway(value):
                        return False, "Invalid gateway format '%s'" % value

        return True, 'Valid!'

    def _is_valid_global_config(global_config):
        """Valid the format of 'global' section in config"""

        required_fields = ['nameservers', 'search_path', 'gateway']
        global_keys = global_config.keys()
        for key in required_fields:
            if key not in global_keys:
                error_msg = ("Missing %s in global config of networking config"
                             % key)
                return False, error_msg

            value = global_config[key]
            if not value:
                error_msg = ("Value of %s in global config cannot be None!" %
                             key)
                return False, error_msg

            if key == 'nameservers':
                nameservers = [nameserver for nameserver in value.split(',')
                               if nameserver]
                for nameserver in nameservers:
                    if not is_valid_ip(nameserver):
                        return (
                            False,
                            "The nameserver format is invalid! '%s'" % value
                            )

            elif key == 'gateway' and not is_valid_gateway(value):
                return False, "The gateway format is invalid! '%s'" % value

        return True, 'Valid!'

    #networking_keys = networking.keys()
    is_valid = False
    msg = None