import os
import re
import errno

from leapp.actors import Actor
from leapp.models import PersistentNetNamesFacts, PersistentNetNamesFactsInitramfs
from leapp.models import RenamedInterface, RenamedInterfaces, InitrdIncludes
from leapp.tags import ApplicationsPhaseTag, IPUWorkflowTag

LINK_FILE_TEMPLATE = """# Generated by LEAPP
[Match]
MACAddress={}

[Link]
Name={}
"""


class PersistentNetNamesConfig(Actor):
    """
    Generate udev persistent network naming configuration

    This actor generates systemd-udevd link files for each physical ethernet interface present on RHEL-7
    in case we notice that interace name differs on RHEL-8. Link file configuration will assign RHEL-7 version of
    a name. Actors produces list of interfaces which changed name between RHEL-7 and RHEL-8.
    """

    name = 'persistentnetnamesconfig'
    consumes = (PersistentNetNamesFacts, PersistentNetNamesFactsInitramfs)
    produces = (RenamedInterfaces, InitrdIncludes)
    tags = (ApplicationsPhaseTag, IPUWorkflowTag)
    initrd_files = []

    def generate_link_file(self, interface):

        try:
            os.makedirs('/etc/systemd/network')
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

        link_file = '/etc/systemd/network/10-leapp-{}.link'.format(interface.name)
        with open(link_file, 'w') as f:
            f.write(LINK_FILE_TEMPLATE.format(interface.mac, interface.name))

        self.initrd_files.append(link_file)

    def process(self):
        rhel7_ifaces = next(self.consume(PersistentNetNamesFacts)).interfaces
        rhel8_ifaces = next(self.consume(PersistentNetNamesFactsInitramfs)).interfaces

        sorted(rhel7_ifaces, key=lambda iface: iface.name)
        sorted(rhel8_ifaces, key=lambda iface: iface.name)

        rhel7_ifaces_map = {iface.mac: iface for iface in rhel7_ifaces}
        rhel8_ifaces_map = {iface.mac: iface for iface in rhel8_ifaces}

        renamed_interfaces = []

        if rhel7_ifaces != rhel8_ifaces:
            for iface in rhel7_ifaces:
                rhel7_name = rhel7_ifaces_map[iface.mac].name
                rhel8_name = rhel8_ifaces_map[iface.mac].name

                if rhel7_name != rhel8_name:
                    self.log.warning('Detected interface rename {} -> {}.'.format(rhel7_name, rhel8_name))

                    if re.search('eth[0-9]+', iface.name) is not None:
                        self.log.warning('Interface named using eth prefix, refusing to generate link file')
                        renamed_interfaces.append(RenamedInterface(**{'rhel7_name': rhel7_name,
                                                                      'rhel8_name': rhel8_name}))
                        continue
                    else:
                        # TODO(msekleta): we need to introduce another actor which will
                        # # install generated link files to RHEL-8 initrd image
                        self.generate_link_file(iface)

        self.produce(RenamedInterfaces(renamed=renamed_interfaces))
        self.produce(InitrdIncludes(files=self.initrd_files))
