import fcntl
import logging
import socket
import struct
from os import listdir, path
from re import search as research
from subprocess import PIPE, Popen

logger = logging.getLogger(__name__)
stream = logging.StreamHandler()
logger.addHandler(stream)


def get_ip(iface='ens2'):

    ''' Get ip address from an interface if applicable

    :param iface: Interface name. Type: str

    '''

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sockfd = sock.fileno()
    SIOCGIFADDR = 0x8915
    ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)

    try:
        res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
    except:
        logger.debug("No ip addresses assigned to %s" % iface)
        return None

    ip = struct.unpack('16sH2x4s8x', res)[2]
    return socket.inet_ntoa(ip)


def get_nics():

    ''' List nics '''

    nics = []
    nics_list = listdir('/sys/class/net/')
    for nic_name in nics_list:
        if research('(br|bond|ens|enp|eth|one|ten|fourty)[0-9]+', nic_name):

            # Interface should be in "up" state in order to get carrier status
            Popen("ip li set dev " + nic_name + " up", shell=True, stdout=PIPE)

            with open("/sys/class/net/" + nic_name + "/carrier", 'r') as f:
                try:
                    carrier = int(f.read())
                except:
                    carrier = 0

            bond = ""
            if path.isfile("/sys/class/net/" + nic_name + "/master/uevent"):
                with open(
                    "/sys/class/net/" + nic_name + "/master/uevent", 'r'
                ) as f:
                    for line in f:
                        sline = line.strip()
                        if 'INTERFACE=bond' in sline:
                            bond = sline.split('=')[1]
            if len(bond) == 0:
                with open("/sys/class/net/" + nic_name + "/address", 'r') as f:
                    macaddr = f.read().strip()
            else:
                with open("/proc/net/bonding/" + bond, 'r') as f:
                    line = f.readline()
                    if_struct = False
                    while line:
                        sline = line.strip()
                        if 'Slave Interface: ' + nic_name in sline and not if_struct:
                            if_struct = True
                        if 'Permanent HW addr: ' in sline and if_struct:
                            macaddr = sline.split()[3]
                            break
                        line = f.readline()

            with open("/sys/class/net/" + nic_name + "/mtu", 'r') as f:
                mtu = f.read()

            ip = str(get_ip(nic_name))

            nics.append([nic_name, ip, macaddr, carrier, mtu])

    return sorted(nics)


def get_ten_pci():

    ''' List ten nics pci addresses '''

    nics = []
    nics_list = listdir('/sys/class/net/')
    for nic_name in nics_list:
        if research('ten[0-9]+', nic_name):
            with open(
                "/sys/class/net/" + nic_name + "/device/uevent", 'r'
            ) as f:
                for line in f:
                    sline = line.strip()
                    if "PCI_SLOT_NAME=" in sline:
                        nics.append([nic_name, sline.split("=")[1]])

    return sorted(nics)


def mesh_ping(mesh):

    ''' One to many ICMP check

    :param hosts: Target hosts. Type: list of ip addresses

    '''

    io = []
    minion_id = __salt__['config.get']('id')

    for host, hostobj in mesh:
        if host == minion_id:
            for mesh_net, addr, targets in hostobj:
                if addr in targets:
                    targets.remove(addr)
                for tgt in targets:
                    # This one will run in parallel with everyone else
                    worker = Popen(
                        "ping -c 1 -w 1 -W 1 " + str(tgt),
                        shell=True, stdout=PIPE, stderr=PIPE
                    )
                    ping_out = worker.communicate()[0]
                    if worker.returncode != 0:
                        io.append(
                            mesh_net + ': ' + addr + ' -> ' + tgt + ': Failed'
                        )

    return io


def minion_list():

    ''' List registered minions '''

    return listdir('/etc/salt/pki/master/minions/')


def verify_addresses():

    ''' Verify addresses taken from pillars '''

    nodes = nodes_addresses()
    verifier = {}
    failed = []

    for node, nodeobj in nodes:
        for item in nodeobj:
            addr = item[1]
            if addr in verifier:
                failed.append([node, verifier[addr], addr])
            else:
                verifier[addr] = node

    if failed:
        logger.error("FAILED. Duplicates found")
        logger.error(failed)
        return False
    else:
        logger.setLevel(logging.INFO)
        logger.info(["PASSED"])
        return True


def nodes_addresses():

    ''' List servers addresses '''

    compound = 'linux:network:interface'
    out = __salt__['saltutil.cmd'](
        tgt='I@' + compound,
        tgt_type='compound',
        fun='pillar.get',
        arg=[compound],
        timeout=10
    ) or None

    servers = []
    for minion in minion_list():
        addresses = []
        if minion in out:
            ifaces = out[minion]['ret']
            for iface in ifaces:
                ifobj = ifaces[iface]
                if ifobj['enabled'] and 'address' in ifobj:
                    if 'mesh' in ifobj:
                        mesh = ifobj['mesh']
                    else:
                        mesh = 'default'
                    addresses.append([mesh, ifobj['address']])
            servers.append([minion, addresses])

    return servers


def get_mesh():

    ''' Build addresses mesh '''

    full_mesh = {}
    nodes = nodes_addresses()

    for node, nodeobj in nodes:
        for item in nodeobj:
            mesh = item[0]
            addr = item[1]
            if mesh not in full_mesh:
                full_mesh[mesh] = []
            full_mesh[mesh].append(addr)

    for node, nodeobj in nodes:
        for item in nodeobj:
            mesh = item[0]
            tgts = full_mesh[mesh]
            item.append(tgts)

    return nodes


def ping_check():

    ''' Ping addresses in a mesh '''

    mesh = get_mesh()
    out = __salt__['saltutil.cmd'](
        tgt='*',
        tgt_type='glob',
        fun='net_checks.mesh_ping',
        arg=[mesh],
        timeout=10
    ) or None

    failed = []

    if out:
        for minion in out:
            ret = out[minion]['ret']
            if ret:
                failed.append(ret)
    else:
        failed = ["No response from minions"]

    if failed:
        logger.error("FAILED")
        logger.error('\n'.join(str(x) for x in failed))
        return False
    else:
        logger.setLevel(logging.INFO)
        logger.info(["PASSED"])
        return True


def get_nics_csv(delim=","):

    ''' List nics in csv format

    :param delim: Delimiter char. Type: str

    '''

    header = "server,nic_name,ip_addr,mac_addr,link,chassis_id,chassis_name,port_mac,port_descr\n"
    io = ""

    # Try to reuse lldp output if possible
    try:
        lldp_info = Popen(
            "lldpcli -f keyvalue s n s",
            shell=True,
            stdout=PIPE
        ).communicate()[0]
    except:
        lldp_info = ""

    for nic in get_nics():
        lldp = ""
        nic_name = nic[0]
        if research('(one|ten|fourty)[0-9]+', nic_name):
            # Check if we can fetch lldp data for that nic
            for line in lldp_info.splitlines():
                chassis = 'lldp.' + nic[0] + '.chassis'
                port = 'lldp.' + nic[0] + '.port'
                if chassis in line or port in line:
                    lldp += delim + line.split('=')[1]
        if not lldp:
            lldp = delim + delim + delim + delim

        io += __salt__['config.get']('id') + \
              delim + nic_name + \
              delim + str(nic[1]).strip() + \
              delim + str(nic[2]).strip() + \
              delim + str(nic[3]).strip() + \
              delim + str(nic[4]).strip() + \
              lldp + "\n"

    return header + io
