#!/usr/bin/env python
#
# Copyright 2017 the original author or authors.
#
# 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.
#
from lxml import etree
import structlog
from netconf.nc_rpc.rpc import Rpc
import netconf.nc_common.error as ncerror
from netconf.constants import Constants as C
from netconf.nc_common.utils import qmap, ns

log = structlog.get_logger()

class GetSchema(Rpc):
    def __init__(self, request, request_xml, grpc_client, session, capabilities):
        super(GetSchema, self).__init__(request, request_xml, grpc_client, session)
        self.capabilities = capabilities
        # specific schema parsing required
        self.parse_schema_request(request_xml)
        self._validate_parameters()

    def execute(self):
        if self.rpc_response.is_error:
            return(self.rpc_response)

        log.info('get-schema-request', session=self.session.session_id,
                 request=self.request)

        # Get the yang schema content
        # TODO: Use version as well
        content = self.capabilities.get_schema_content(self.request['identifier'])
        if not content:
            self.rpc_response.is_error = True
            self.rpc_response.node = ncerror.BadMsg('Server Error')
            return

        self.rpc_response.node = self.create_xml_response(content)

        self.rpc_response.is_error = False

        return(self.rpc_response)

    def _validate_parameters(self):
        log.info('validate-parameters', session=self.session.session_id)
        # Validate the GET command
        if self.request:
            try:
                if self.request['command'] != 'get-schema' or \
                        not self.request.has_key('identifier') or \
                        not self.request.has_key('format') or \
                        not self.request.has_key('version'):
                    self.rpc_response.is_error = True
                    self.rpc_response.node = ncerror.BadMsg('Improperly '
                                                            'formatted get '
                                                            'schemas request')
                    return

                if self.request.has_key('filter'):
                    if not self.request.has_key('class'):
                        self.rpc_response.is_error = True
                        self.rpc_response.node = ncerror.BadMsg(
                            'Missing filter sub-element')
                        return

                # Verify that the requested schema exists
                if not self.capabilities.is_schema_supported(self.request[
                                                             'identifier']) \
                        or self.request['format'] != 'yang' :
                    self.rpc_response.is_error = True
                    self.rpc_response.node = ncerror.BadMsg(
                        'Unsupported request')
                    return

            except Exception as e:
                self.rpc_response.is_error = True
                self.rpc_response.node = ncerror.BadMsg(self.request)
                return

    # Parse context-specific parameters
    def parse_schema_request(self, node):
        if not len(node):
            return
        schema_node = node.find(''.join([qmap(C.NCM), 'get-schema']))
        if schema_node is not None:
            for item in ['identifier', 'version', 'format']:
                elem = schema_node.find(''.join([qmap(C.NCM), item]))
                if elem is not None:
                    self.request[item] = elem.text

    def create_xml_response(self, content):
        ns = {}
        ns['xmlns'] = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"

        elem = etree.Element('data', attrib=ns)
        elem.text = unicode(content, "utf-8")
        return elem
