Search in all possible entities (Interfaces, MAC tables, ARP tables, LLDP neighbors),
    using the following mine functions:

    - net.mac
    - net.arp
    - net.lldp
    - net.ipaddrs
    - net.interfaces

    This function has the advantage that it knows where to look, but the output might
    become quite long as returns all possible matches.

    Optional arguments:

    best: ``True``
        Return only the best match with the interfaces IP networks
        when the saerching pattern is a valid IP Address or Network.

    display: ``True``
        Display on the screen or return structured object? Default: ``True`` (return on the CLI).

    CLI Example:

    .. code-block:: bash

        $ sudo salt-run net.find 10.10.10.7

    Output Example:

    .. code-block:: text

        Details for all interfaces that include network 10.10.10.7/32 - only best match returned
        ________________________________________________________________________________________________________________________
        |    Device    | Interface | Interface Description |  UP  | Enabled | Speed [Mbps] |    MAC Address    |  IP Addresses |
        ________________________________________________________________________________________________________________________
        | edge01.flw01 |    irb    |                       | True |   True  |      -1      | 5C:5E:AB:AC:52:B4 | 10.10.10.1/22 |
        ________________________________________________________________________________________________________________________

        ARP Entries for IP 10.10.10.7
        _____________________________________________________________________________
        |    Device    |     Interface     |        MAC        |     IP     |  Age  |
        _____________________________________________________________________________
        | edge01.flw01 | irb.349 [ae0.349] | 2C:60:0C:2A:4C:0A | 10.10.10.7 | 832.0 |
        _____________________________________________________________________________

def find(addr, best=True, display=_DEFAULT_DISPLAY):
    '''
    Search in all possible entities (Interfaces, MAC tables, ARP tables, LLDP neighbors),
    using the following mine functions:

    - net.mac
    - net.arp
    - net.lldp
    - net.ipaddrs
    - net.interfaces

    This function has the advantage that it knows where to look, but the output might
    become quite long as returns all possible matches.

    Optional arguments:

    best: ``True``
        Return only the best match with the interfaces IP networks
        when the saerching pattern is a valid IP Address or Network.

    display: ``True``
        Display on the screen or return structured object? Default: ``True`` (return on the CLI).

    CLI Example:

    .. code-block:: bash

        $ sudo salt-run net.find 10.10.10.7

    Output Example:

    .. code-block:: text

        Details for all interfaces that include network 10.10.10.7/32 - only best match returned
        ________________________________________________________________________________________________________________________
        |    Device    | Interface | Interface Description |  UP  | Enabled | Speed [Mbps] |    MAC Address    |  IP Addresses |
        ________________________________________________________________________________________________________________________
        | edge01.flw01 |    irb    |                       | True |   True  |      -1      | 5C:5E:AB:AC:52:B4 | 10.10.10.1/22 |
        ________________________________________________________________________________________________________________________

        ARP Entries for IP 10.10.10.7
        _____________________________________________________________________________
        |    Device    |     Interface     |        MAC        |     IP     |  Age  |
        _____________________________________________________________________________
        | edge01.flw01 | irb.349 [ae0.349] | 2C:60:0C:2A:4C:0A | 10.10.10.7 | 832.0 |
        _____________________________________________________________________________
    '''
    if not addr:
        if display:
            print('Please type a valid MAC/IP Address / Device / Interface / VLAN')
        return {}

    device = ''
    interface = ''
    mac = ''
    ip = ''  # pylint: disable=invalid-name
    ipnet = None

    results = {
        'int_net': [],
        'int_descr': [],
        'int_name': [],
        'int_ip': [],
        'int_mac': [],
        'int_device': [],
        'lldp_descr': [],
        'lldp_int': [],
        'lldp_device': [],
        'lldp_mac': [],
        'lldp_device_int': [],
        'mac_device': [],
        'mac_int': [],
        'arp_device': [],
        'arp_int': [],
        'arp_mac': [],
        'arp_ip': []
    }

    if isinstance(addr, int):
        results['mac'] = findmac(vlan=addr, display=display)
        if not display:
            return results
        else:
            return None

    try:
        mac = napalm_helpers.convert(napalm_helpers.mac, addr)
    except IndexError:
        # no problem, let's keep searching
        pass
    if salt.utils.network.is_ipv6(addr):
        mac = False
    if not mac:
        try:
            ip = napalm_helpers.convert(napalm_helpers.ip, addr)  # pylint: disable=invalid-name
        except ValueError:
            pass
        ipnet = _get_network_obj(addr)
        if ipnet:
            results['int_net'] = interfaces(ipnet=ipnet, best=best, display=display)
        if not (ipnet or ip):
            # search in all possible places
            # display all interfaces details
            results['int_descr'] = interfaces(pattern=addr, display=display)
            results['int_name'] = interfaces(interface=addr, display=display)
            results['int_device'] = interfaces(device=addr, display=display)
            # search in LLDP details
            results['lldp_descr'] = lldp(pattern=addr, display=display)
            results['lldp_int'] = lldp(interface=addr, display=display)
            results['lldp_device'] = lldp(device=addr, display=display)
            # search in MAC Address tables
            results['mac_device'] = findmac(device=addr, display=display)
            results['mac_int'] = findmac(interface=addr, display=display)
            # search in ARP tables
            results['arp_device'] = findarp(device=addr, display=display)
            results['arp_int'] = findarp(interface=addr, display=display)
            if not display:
                return results
    if mac:
        results['int_descr'] = findmac(mac=mac, display=display)
        results['arp_mac'] = findarp(mac=mac, display=display)
        results['lldp_mac'] = lldp(chassis=mac, display=display)
    if ip:
        results['arp_ip'] = findarp(ip=ip, display=display)

    # let's search in Interfaces

    if mac:
        device, interface, ips = _find_interfaces_ip(mac)
        ip = ', '.join(ips)  # pylint: disable=invalid-name
        if device and interface:
            title = 'Interface {interface} on {device} has the physical address ({mac})'.format(
                interface=interface,
                device=device,
                mac=mac
            )
            results['int_mac'] = interfaces(device=device, interface=interface, title=title, display=display)

    elif ip:
        device, interface, mac = _find_interfaces_mac(ip)
        if device and interface:
            title = 'IP Address {ip} is set for interface {interface}, on {device}'.format(
                interface=interface,
                device=device,
                ip=ip
            )
            results['int_ip'] = interfaces(device=device, interface=interface, title=title, display=display)

    if device and interface:
        results['lldp_device_int'] = lldp(device, interface, display=display)

    if not display:
        return results