from __future__ import print_function
import re
from MPLSinventory.regexstructure import RegexStructure
from MPLSinventory.telnet import ShowVersion, ShowIPInterfacesBrief, ShowIPBGPSum
from MPLSinventory.tools import search, search_all, assign_attr_if_better
from MPLSinventory.ip_address_tools import IPv4Address, IPv4Interface


class RouterBGP(RegexStructure):
    """Class that analyses and stores the settings for BGP configuration"""

    _single_attributes = {
        'local_as': (r'^s*router\sbgp\s+(\d+)\s*$', int)
    }

    def __init__(self, config):
        super(RouterBGP, self).__init__(config)
        self.neighbors = self._get_bgp_neighbors()

    def _get_bgp_neighbors(self):
        active_neighbors = []
        regex = r'^\s*neighbor\s+(\d+\.\d+\.\d+\.\d+)\s+remote-as\s+(\d+)$'
        all_neighbors = search_all(regex, self.config)
        for neighbor, remote_as in all_neighbors:
            regex = r'^\s*neighbor\s+('+neighbor+')\s+shutdown'
            shutdown = bool(search(regex, self.config))
            if not shutdown:
                active_neighbors.append((IPv4Address(neighbor), int(remote_as)))
        active_neighbors = list(set(active_neighbors))
        return active_neighbors


class QoSClass(RegexStructure):
    """Class that analyses and stores the settings for a QoS class.

    Todo:
    - bandwidth remaining ratio
    -

    """
    _single_attributes = {
        'name':              (r'^\s*class\s(\S+)\s*$', str),
        'bandwidth':         (r'^\s*(?:bandwidth|priority)\s+(\d+)\s*', int),
        'bandwidth_percent': (r'^\s*(?:bandwidth|priority)\spercent\s+(\d+)\s*', int),
        'police':            (r'^\s*(?:police|police\srate)\s(\d+)\s*',
                              lambda x: int(x)/1000)
        }

    def __init__(self, config):
        super(QoSClass, self).__init__(config)


class QoSPolicy(RegexStructure):
    """Class that analyses and stores the settings for a QoS policy.

    Todo:
    -  bandwidth remaining ratio
    """
    _single_attributes = {
        'name':          (r'^\s*policy-map\s+(\S+)\s*$', str),
        'description':   (r'^\s*description\s+(.+)$', str),
        'sub_policy':    (r'^\s*service-policy\s+(\S+)\s*$', str),
        'shaper':        (r'^\s*shape\s+average\s+(\d+)\s*',
                          lambda x: int(x)/1000)
        }

    _multiple_children = {
        'qos_classes': ('class', QoSClass)
    }

    def __init__(self, config):
        super(QoSPolicy, self).__init__(config)
        self.qos_bandwidth = self._find_total_qos_bandwidth()
        self.priority_class = self._find_priority_class()
        if not self.qos_bandwidth and hasattr(self.priority_class, 'bandwidth_percent'):
            self.qos_bandwidth = self._find_total_bandwidth_percent()

    def _find_priority_class(self):
        result = ''
        for class_name, qos_class in self.qos_classes.items():
            if 'priority' in ''.join(qos_class.config[1:]):
                result = qos_class
        return result

    def _find_total_qos_bandwidth(self):
        qos_bandwidth = 0
        for class_name, qos_class in self.qos_classes.items():
            if qos_class.bandwidth:
                qos_bandwidth += qos_class.bandwidth
        return qos_bandwidth

    def _find_total_bandwidth_percent(self):
        qos_bandwidth = 0
        if self.priority_class.bandwidth_percent:
            x1 = self.priority_class.bandwidth_percent
            x2 = self.priority_class.police
            if x1 and x2:
                qos_bandwidth = int(x2/(x1/100.00))
        return qos_bandwidth


class Interface(RegexStructure):
    """Class that analyses and stores the settings for a Router interface.

        Todo:
      - secondary ip's
      - secondary standby groups
      - vrf
    """
    _single_attributes = {
        'name':               (r'^interface\s(\S+)\s*.*$', str),
        'description':        (r'^\s*description\s+(.+)$', str),
        'ip':                 (r'^\s*ip\saddress\s(\d+\.\d+\.\d+\.\d+\s+\d+\.\d+\.\d+\.\d+)\s*$',
                               lambda ip: IPv4Interface(re.sub(r'\s+', '/', ip))),
        'ip_unnumbered':      (r'^\s*ip\s+unnumbered\s+(\S+)\s*$', str),
        'ip_negotiated':      (r'^\s*ip\saddress\s(negotiated)\s*$', str),
        'admin_bandwidth':    (r'^\s*bandwidth\s+(\d+)', int),
        'hsrp':               (r'^\s*standby\s+\d+\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s*$',
                               IPv4Address),
        'policy_in':          (r'^\s*service-policy\s+input\s+(\S+)\s*$', str),
        'policy_out':         (r'^\s*service-policy\s+output\s+(\S+)\s*$', str),
        'atm_bandwidth':      (r'^\s*(?:cbr|vbr-nrt)\s+(\d+)\s*', int),
        'rate_limit':         (r'^\s*rate-limit\s+output\s+(\d+)\s',
                               lambda x: int(x)/1000),
        'crypto':             (r'^\s*(crypto.+)$', str),
        'dialer_pool':        (r'^\s*dialer\s+pool\s+(\d+)\s*$', int),
        'dialer_pool_member': (r'^\s*dialer\s+pool-member\s+(\d+)\s*$', int),
        'dial_pool_number':   (r'^\s*.+dial-pool-number\s+(\d+)\s*$', int)
        }

    _json_simplify = ['parent']

    def __init__(self, config):
        super(Interface, self).__init__(config)
        self.parent = ''
        self.status = ''
        self._load_interface_details()    # (self)?

    def _load_interface_details(self):
        regex = r'^\s*ip\s+helper-address\s+(\d+\.\d+\.\d+\.\d+)\s*$'
        helpers = search_all(regex, self.config)
        helpers = map(lambda ip: IPv4Address(ip), helpers)
        self.helpers = list(set(helpers))

        regex = r'^\s*Vlan\s*(\d+)\s*$'
        vlan = search(regex, self.name)
        if not vlan:
            regex = r'^\s*encapsulation\s+dot1Q\s+(\d+)\s*$'
            vlan = search(regex, self.config)
        if vlan:
            self.vlan = int(vlan)


class Router(RegexStructure):