#!/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.
#
import structlog
from netconf.nc_rpc.rpc import Rpc
import netconf.nc_common.error as ncerror
from twisted.internet.defer import inlineCallbacks, returnValue
import dicttoxml
from netconf.nc_common.utils import qmap, ns
from netconf.constants import Constants as C
from netconf.grpc_client.nc_rpc_mapper import \
    get_nc_rpc_mapper_instance

log = structlog.get_logger()


class VolthaRpc(Rpc):
    def __init__(self, request, request_xml, grpc_client, session,
                 capabilities):
        super(VolthaRpc, self).__init__(request, request_xml, grpc_client,
                                        session, capabilities)
        self.service = None
        self.method = None
        self.metadata = None
        self._extract_parameters()
        if not self.rpc_response.is_error:
            self._validate_parameters()

    @inlineCallbacks
    def execute(self):
        if self.rpc_response.is_error:
            returnValue(self.rpc_response)

        log.info('voltha-rpc-request', session=self.session.session_id,
                 request=self.request)

        # Execute the request
        res_dict = yield self.grpc_client.invoke_voltha_rpc(
            service=self.service,
            method=self.method,
            params=self.request['params'],
            metadata=self.metadata)

        # convert dict to xml
        xml = dicttoxml.dicttoxml(res_dict, attr_type=True)
        log.info('voltha-info', res=res_dict, xml=xml)

        root_elem = self.get_root_element(xml)

        # Build the yang response
        self.rpc_response.node = self.rpc_response.build_yang_response(
            root_elem, self.request, custom_rpc=True)
        self.rpc_response.is_error = False

        returnValue(self.rpc_response)

    def _validate_parameters(self):
        log.info('validate-parameters', session=self.session.session_id)
        # For now just validate that the command is presenf
        if self.request:
            try:
                if self.request['command'] is None:
                    self.rpc_response.is_error = True
                    self.rpc_response.node = ncerror.BadMsg(self.request_xml)
                    return

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

    def _extract_parameters(self):
        try:
            rpc_node = self.request_xml.find(''.join(
                [qmap(C.VOLTHA),
                 self.request['command']])
            )
            self.request['params'] = {}
            if rpc_node is not None:
                for r in rpc_node:
                    self.request['params'][
                        r.tag.replace(qmap(C.VOLTHA), "")] = r.text

            # Remove the subclass element in the request if it is present as
            # it is not required for rpc calls
            if self.request.has_key('subclass'):
                self.request.pop('subclass', None)

            # Extract the service and method from the rpc command
            command = self.request['command'].split('-')
            if len(command) != 2:
                log.debug('invalid-format', command=self.request['command'])
                raise

            self.service = command[0]
            self.method = command[1]
            if self.request.has_key('metadata'):
                self.metadata = self.request['metadata']

        except Exception as e:
            self.rpc_response.is_error = True
            self.rpc_response.node = ncerror.BadMsg(self.request_xml)
            log.exception('params-parsing-error', xml=self.request_xml, e=e)
