#
# Copyright 2017-present Adtran, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import xmltodict
import re
import structlog
from twisted.internet.defer import inlineCallbacks, returnValue, succeed

log = structlog.get_logger()

_acl_list = {}      # Key -> device-id -> Name: List of encoded EVCs

ACL_NAME_FORMAT = 'VOLTHA-ACL-{}-{}'  # format(flow_entry.handler.device_id, flow_entry.flow.id)
ACL_NAME_REGEX_ALL = 'VOLTHA-ACL-*'

class ACL(object):
    """
    Class to wrap Trap-to-Controller functionality
    """
    def __init__(self, flow_entry):
        self._installed = False
        self._status_message = None
        self._parent = flow_entry           # FlowEntry parent
        self._flow = flow_entry.flow
        self._handler = flow_entry.handler
        self._name = ACL.flow_to_name(flow_entry)
        self._rule_name = ACL.flow_to_ace_name(flow_entry)
        self._eth_type = flow_entry.eth_type
        self._ip_protocol = flow_entry.ip_protocol
        self._ipv4_dst = flow_entry.ipv4_dst
        self._src_port = flow_entry.udp_src
        self._dst_port = flow_entry.udp_dst
        self._exception = False
        self._enabled = True
        self._valid = self._decode()

    def __str__(self):
        return 'ACL: {}, Installed: {}, L2: {}, L3/4: {}'.format(self.name,
                                                                 self._installed,
                                                                 self.is_l2_exception,
                                                                 self.is_l3_l4_exception)

    @property
    def name(self):
        return self._name

    @property
    def installed(self):
        return self._installed

    @property
    def is_l2_exception(self):
        from flow_entry import FlowEntry
        return self._eth_type not in (None,
                                      FlowEntry.EtherType.IPv4,
                                      FlowEntry.EtherType.IPv6)

    @property
    def is_l3_l4_exception(self):
        return not self.is_l2_exception and self._ip_protocol is not None

    @staticmethod
    def _xml_header(operation=None):
        return '<access-lists xmlns="http://www.adtran.com/ns/yang/adtran-ietf-access-control-list"\
                xmlns:adtn-ietf-ns-acl="http://www.adtran.com/ns/yang/adtran-ietf-ns-access-control-list"><acl{}>'.\
            format('' if operation is None else ' xc:operation="{}"'.format(operation))

    @staticmethod
    def _xml_trailer():
        return '</acl></access-lists>'

    def _xml_action(self):
        xml = '<actions>'
        if self._exception:
            xml += '<adtn-ietf-ns-acl:exception-to-cpu/>'
        else:
            xml += '<permit/>'
        xml += '</actions>'
        return xml

    def _ace_l2(self):
        xml = '<ace>'
        xml += '<rule-name>{}</rule-name>'.format(self._rule_name)
        xml += '<matches><l2-acl><ether-type>{:04x}</ether-type></l2-acl></matches>'.format(self._eth_type)
        xml += self._xml_action()
        xml += '</ace>'
        return xml

    def _ace_l2_l3_ipv4(self):
        xml = '<ace>'
        xml += '<rule-name>{}</rule-name>'.format(self._rule_name)
        xml += '<matches><l2-l3-ipv4-acl>'
        xml += '<ether-type>{:04X}</ether-type>'.format(self._eth_type)

        if self._ip_protocol is not None:
            xml += '<protocol>{}</protocol>'.format(self._ip_protocol)
        if self._ipv4_dst is not None:
            xml += '<destination-ipv4-network>{}/32</destination-ipv4-network>'.format(self._ipv4_dst)
        if self._src_port is not None:
            xml += '<source-port-range><lower-port>{}</lower-port><operation>eq</operation></source-port-range>'.\
                format(self._src_port)
        if self._dst_port is not None:
            xml += '<destination-port-range><lower-port>' + \
                   '{}</lower-port><operations>eq</operations></destination-port-range>'.format(self._dst_port)

        xml += '</l2-l3-ipv4-acl></matches>'
        xml += self._xml_action()
        xml += '</ace>'
        return xml

    def _ace_any(self):
        xml = '<ace>'
        xml += '<rule-name>{}</rule-name>'.format(self._rule_name)
        xml += '<matches><any-acl/></matches>'
        xml += self._xml_action()
        xml += '</ace>'
        return xml

    def _acl_eth(self):
        xml = '<acl-type>eth-acl</acl-type>'
        xml += '<acl-name>{}</acl-name>'.format(self._name)
        return xml

    def _acl_l4(self):
        xml = '<acl-type>mixed-l2-l3-ipv4-acl</acl-type>'
        xml += '<acl-name>{}</acl-name>'.format(self._name)
        return xml

    def _acl_any(self):
        xml = '<acl-type>any-acl</acl-type>'
        xml += '<acl-name>{}</acl-name>'.format(self._name)
        return xml

    def _install_xml(self):
        xml = ACL._xml_header('create')
        if self.is_l2_exception:
            xml += self._acl_eth()
            xml += '<aces>{}</aces>'.format(self._ace_l2())
        elif self.is_l3_l4_exception:
            xml += self._acl_l4()
            xml += '<aces>{}</aces>'.format(self._ace_l2_l3_ipv4())
        else:
            xml += self._acl_any()
            xml += '<aces>{}</aces>'.format(self._ace_any())

        xml += ACL._xml_trailer()
        return xml

    def _remove_xml(self):
        xml = ACL._xml_header('delete')
        if self.is_l2_exception:
            xml += self._acl_eth()
        elif self.is_l3_l4_exception:
            xml += self._acl_l4()
        else:
            xml += self._acl_any()
        xml += ACL._xml_trailer()
        return xml

    def evc_map_ingress_xml(self):
        """ Individual ACL specific XML for the EVC MAP """

        xml = '<adtn-evc-map-acl:acl-type '
        fmt = 'xmlns:adtn-ietf-acl="http://www.adtran.com/ns/yang/adtran-ietf-access-control-list">adtn-ietf-acl:{}'\
              '</adtn-evc-map-acl:acl-type>'

        if self.is_l2_exception:
            xml += fmt.format('eth-acl')

        elif self.is_l3_l4_exception:
            xml += fmt.format('mixed-l2-l3-ipv4-acl')

        else:
            xml += fmt.format('any-acl')

        xml += '<adtn-evc-map-acl:acl-name>{}</adtn-evc-map-acl:acl-name>'.format(self.name)
        return xml

    @staticmethod
    def create(flow_entry):
        return ACL(flow_entry)

    @staticmethod
    def flow_to_name(flow_entry):
        return 'VOLTHA-ACL-{}-{}'.format(flow_entry.handler.device_id, flow_entry.flow.id)

    @staticmethod
    def flow_to_ace_name(flow_entry):
        return 'VOLTHA-ACE-{}-{}'.format(flow_entry.handler.device_id, flow_entry.flow.id)

    @property
    def valid(self):
        return self._valid

    @property
    def installed(self):
        return self._installed

    @property
    def status(self):
        return self._status_message

    @inlineCallbacks
    def install(self):
        log.debug('installing-acl', installed=self._installed)

        if not self._installed and self._enabled:
            if self._handler.device_id not in _acl_list:
                _acl_list[self._handler.device_id] = {}

            acls_installed = _acl_list[self._handler.device_id]
            if self._name in acls_installed:
                self._status_message = "ACL '{}' id already installed".format(self._name)
                raise Exception(self._status_message)

            try:
                acl_xml = self._install_xml()
                log.debug('install-xml', xml=acl_xml, name=self._name)

                results = yield self._handler.netconf_client.edit_config(acl_xml)
                self._installed = results.ok
                self._status_message = '' if results.ok else results.error

                if self._installed:
                    acls_installed[self._name] = self

            except Exception as e:
                log.exception('install-failure', name=self._name, e=e)
                raise

        returnValue(self._installed and self._enabled)

    @inlineCallbacks
    def remove(self):
        log.debug('removing-acl', installed=self._installed)

        if self._installed:
            acl_xml = self._remove_xml()
            log.info('remove-xml', xml=acl_xml, name=self._name)

            results = yield self._handler.netconf_client.edit_config(acl_xml)
            self._installed = not results.ok
            self._status_message = '' if results.ok else results.error

            if not self._installed:
                acls_installed = _acl_list.get(self._handler.device_id)
                if acls_installed is not None and self._name in acls_installed:
                    del acls_installed[self._name]

        returnValue(not self._installed)

    def enable(self):
        if not self._enabled:
            self._enabled = False
            raise NotImplemented("TODO: Implement this")

    def disable(self):
        if self._enabled:
            self._enabled = True
            raise NotImplemented("TODO: Implement this")

    def _decode(self):
        """
        Examine the field settings and set ACL up for requested fields
        """
        # If EtherType is not None and not IP, this is an L2 exception
        self._exception = self.is_l2_exception or self.is_l3_l4_exception
        return True

    # BULK operations

    @staticmethod
    def enable_all():
        raise NotImplemented("TODO: Implement this")

    @staticmethod
    def disable_all():
        raise NotImplemented("TODO: Implement this")

    @staticmethod
    def remove_all(client, regex_=ACL_NAME_REGEX_ALL):
        """
        Remove all matching ACLs from hardware
        :param client: (ncclient) NETCONF Client to use
        :param regex_: (String) Regular expression for name matching
        :return: (deferred)
        """
        # Do a 'get' on the evc config an you should get the names
        get_xml = """
        <filter>
          <access-lists xmlns="http://www.adtran.com/ns/yang/adtran-ietf-access-control-list">
            <acl><acl-type/><acl-name/></acl>
          </access-lists>
        </filter>
        """
        log.info('query', xml=get_xml, regex=regex_)

        def request_failed(results, operation):
            log.error('{}-failed'.format(operation), results=results)

        def delete_complete(results):
            log.debug('delete-complete', results=results)

        def do_delete(rpc_reply, regexpr):
            log.debug('query-complete', rpc_reply=rpc_reply)

            if rpc_reply.ok:
                result_dict = xmltodict.parse(rpc_reply.data_xml)
                entries = result_dict['data']['access-lists'] if 'access-lists' in result_dict['data'] else {}

                if 'acl' in entries:
                    p = re.compile(regexpr)

                    pairs = []
                    if isinstance(entries['acl'], list):
                        pairs = { (entry['acl-type'], entry['acl-name']) for entry in entries['acl']
                                 if 'acl-name' in entry and 'acl-type' in entry and p.match(entry['acl-name'])}
                    else:
                        if 'acl' in entries:
                            entry = entries['acl']
                            if 'acl-name' in entry and 'acl-type' in entry and p.match(entry['acl-name']):
                                pairs = [ (entry['acl-type'], entry['acl-name']) ]

                    if len(pairs) > 0:
                        del_xml = '<access-lists xmlns="http://www.adtran.com/ns/yang/adtran-ietf-access-control-list">'
                        for pair in pairs:
                            del_xml += '<acl xc:operation = "delete">'
                            del_xml += '<acl-type>{}</acl-type>'.format(pair[0])
                            del_xml += '<acl-name>{}</acl-name>'.format(pair[1])
                            del_xml += '</acl>'
                        del_xml += '</access-lists>'
                        log.debug('removing', xml=del_xml)

                        return client.edit_config(del_xml)

            return succeed('no entries')

        d = client.get(get_xml)
        d.addCallbacks(do_delete, request_failed, callbackArgs=[regex_], errbackArgs=['get'])
        d.addCallbacks(delete_complete, request_failed, errbackArgs=['edit-config'])
        return d
