0x0000000000000000
  #   lY>*a,jvApNFe׿ ?     # This file is part of cloud-init. See LICENSE file for license information.

import os
import re

import six

from cloudinit.distros.parsers import networkmanager_conf
from cloudinit.distros.parsers import resolv_conf
from cloudinit import log as logging
from cloudinit import util

from configobj import ConfigObj

from . import renderer
from .network_state import (
    is_ipv6_addr, net_prefix_to_ipv4_mask, subnet_is_ipv6, IPV6_DYNAMIC_TYPES)

LOG = logging.getLogger(__name__)
NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf"
KNOWN_DISTROS = ['centos', 'fedora', 'rhel', 'suse']


def _make_header(sep='#'):
    lines = [
        "Created by cloud-init on instance boot automatically, do not edit.",
        "",
    ]
    for i in range(0, len(lines)):
        if lines[i]:
            lines[i] = sep + " " + lines[i]
        else:
            lines[i] = sep
    return "\n".join(lines)


def _is_default_route(route):
    default_nets = ('::', '0.0.0.0')
    return route['prefix'] == 0 and route['network'] in default_nets


def _quote_value(value):
    if re.search(r"\s", value):
        # This doesn't handle complex cases...
        if value.startswith('"') and value.endswith('"'):
            return value
        else:
            return '"%s"' % value
    else:
        return value


def enable_ifcfg_rh(path):
    """Add ifcfg-rh to NetworkManager.cfg plugins if main section is present"""
    config = ConfigObj(path)
    if 'main' in config:
        if 'plugins' in config['main']:
            if 'ifcfg-rh' in config['main']['plugins']:
                return
        else:
            config['main']['plugins'] = []

        if isinstance(config['main']['plugins'], list):
            config['main']['plugins'].append('ifcfg-rh')
        else:
            config['main']['plugins'] = [config['main']['plugins'], 'ifcfg-rh']
        config.write()
        LOG.debug('Enabled ifcfg-rh NetworkManager plugins')


class ConfigMap(object):
    """Sysconfig like dictionary object."""

    # Why does redhat prefer yes/no to true/false??
    _bool_map = {
        True: 'yes',
        False: 'no',
    }

    def __init__(self):
        self._conf = {}

    def __setitem__(self, key, value):
        self._conf[key] = value

    def __getitem__(self, key):
        return self._conf[key]

    def __contains__(self, key):
        return key in self._conf

    def drop(self, key):
        self._conf.pop(key, None)

    def __len__(self):
        return len(self._conf)

    def skip_key_value(self, key, val):
        """Skip the pair key, value if it matches a certain rule."""
        return False

    def to_string(self):
        buf = six.StringIO()
        buf.write(_make_header())
        if self._conf:
            buf.write("\n")
        for key in sorted(self._conf.keys()):
            value = self._conf[key]
            if self.skip_key_value(key, value):
                continue
            if isinstance(value, bool):
                value = self._bool_map[value]
            if not isinstance(value, six.string_types):
                value = str(value)
            buf.write("%s=%s\n" % (key, _quote_value(value)))
        return buf.getvalue()


class Route(ConfigMap):
    """Represents a route configuration."""

    def __init__(self, route_name, base_sysconf_dir,
                 ipv4_tpl, ipv6_tpl):
        super(Route, self).__init__()
        self.last_idx = 1
        self.has_set_default_ipv4 = False
        self.has_set_default_ipv6 = False
        self._route_name = route_name
        self._base_sysconf_dir = base_sysconf_dir
        self.route_fn_tpl_ipv4 = ipv4_tpl
        self.route_fn_tpl_ipv6 = ipv6_tpl

    def copy(self):
        r = Route(self._route_name, self._base_sysconf_dir,
                  self.route_fn_tpl_ipv4, self.route_fn_tpl_ipv6)
        r._conf = self._conf.copy()
        r.last_idx = self.last_idx
        r.has_set_default_ipv4 = self.has_set_default_ipv4
        r.has_set_default_ipv6 = self.has_set_default_ipv6
        return r
