# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------
# HP.ProCurve.get_lldp_neighbors
# ---------------------------------------------------------------------
# Copyright (C) 2007-2019 The NOC Project
# See LICENSE for details
# ---------------------------------------------------------------------

# Python modules
import re

# NOC modules
from noc.core.script.base import BaseScript
from noc.sa.interfaces.igetlldpneighbors import IGetLLDPNeighbors


class Script(BaseScript):
    name = "HP.ProCurve.get_lldp_neighbors"
    interface = IGetLLDPNeighbors

    rx_localport = re.compile(r"^\s*(\S+)\s*\|\s*local\s+(\d+)\s+.+?$", re.MULTILINE)
    rx_split = re.compile(r"^\s*----.+?\n", re.MULTILINE | re.DOTALL)
    rx_line = re.compile(r"^\s*(?P<port>\S+)\s*|", re.MULTILINE | re.DOTALL)
    # rx_chassis_id=re.compile(r"^\s*ChassisId\s*:\s*(.{17})",re.MULTILINE|re.DOTALL|re.IGNORECASE)
    rx_chassis_id = re.compile(
        r"ChassisType\s*:\s*(\S+).+?ChassisId\s*:\s*([a-zA-Z0-9\.\- ]+)",
        re.MULTILINE | re.DOTALL | re.IGNORECASE,
    )
    rx_port_id = re.compile(r"^\s*PortId\s*:\s*(.+?)\s*$", re.MULTILINE | re.DOTALL | re.IGNORECASE)
    rx_sys_name = re.compile(
        r"^\s*SysName\s*:\s*(.+?)\s*$", re.MULTILINE | re.DOTALL | re.IGNORECASE
    )
    rx_sys_descr = re.compile(
        r"^\s*System Descr\s*:\s*(.+?)\s*$", re.MULTILINE | re.DOTALL | re.IGNORECASE
    )
    rx_port_descr = re.compile(
        r"^\s*PortDescr\s*:\s*(.+?)\s*$", re.MULTILINE | re.DOTALL | re.IGNORECASE
    )
    rx_cap = re.compile(r"^\s*System Capabilities Enabled\s*:(.*?)$", re.MULTILINE | re.IGNORECASE)

    def execute(self):
        r = []
        # HP.ProCurve advertises local(7) port sub-type, so local_interface_id parameter required
        # Collect data
        local_port_ids = {}  # name -> id
        for port, local_id in self.rx_localport.findall(self.cli("show lldp info local-device")):
            local_port_ids[port] = int(local_id)
        # Get neighbors
        v = self.cli("show lldp info remote-device")
        for ln in self.rx_split.split(v)[1].splitlines():
            ln = ln.strip()
            if not ln:
                continue
            match = self.rx_line.search(ln)
            if not match:
                continue
            local_interface = match.group("port")
            i = {"local_interface": local_interface, "neighbors": []}
            # Add locally assigned port id, if exists
            if local_interface in local_port_ids:
                i["local_interface_id"] = local_port_ids[local_interface]
            v = self.cli("show lldp info remote-device %s" % local_interface)
            # Get chassis id
            match = self.rx_chassis_id.search(v)
            if not match:
                continue
            remote_chassis_id_subtype = {
                "mac-address": 4,
                "network-address": 5,
                "local": 7,  # @todo: check
            }[match.group(1)]
            remote_chassis_id = match.group(2).strip().replace(" ", "")
            if remote_chassis_id_subtype == 4:
                remote_chassis_id = "%s-%s" % (
                    remote_chassis_id[:6],
                    remote_chassis_id[6:],
                )  # Convert to HP-style mac
            else:
                remote_chassis_id = remote_chassis_id.strip()
            n = {
                "remote_chassis_id": remote_chassis_id,
                "remote_port_subtype": 5,
                "remote_chassis_id_subtype": remote_chassis_id_subtype,
            }
            # Get remote port
            match = self.rx_port_id.search(v)
            if not match:
                continue
            n["remote_port"] = match.group(1)
            # Get remote system name
            match = self.rx_sys_name.search(v)
            if match:
                n["remote_system_name"] = match.group(1)
            # Get remote system description
            match = self.rx_sys_descr.search(v)
            if match:
                n["remote_system_description"] = match.group(1)
            # Get remote port description
            match = self.rx_port_descr.search(v)
            if match:
                n["remote_port_description"] = match.group(1)
            # Get capabilities
            caps = 0
            match = self.rx_cap.search(v)
            if match:
                for c in match.group(1).strip().split(", "):
                    if not c:
                        continue
                    caps |= {
                        "other": 1,
                        "repeater": 2,
                        "bridge": 4,
                        "wlanaccesspoint": 8,
                        "router": 16,
                        "telephone": 32,
                        "docsis": 64,
                        "station": 128,
                        "station-only": 128,
                    }[c.lower()]
            n["remote_capabilities"] = caps
            i["neighbors"] += [n]
            r += [i]
        return r
