# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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 uuid, json
from flask import request
from flask_restful import Resource
from common.proto.context_pb2 import Empty
from common.proto.qkd_app_pb2 import App, QKDAppTypesEnum
from common.Constants import DEFAULT_CONTEXT_NAME
from context.client.ContextClient import ContextClient
from qkd_app.client.QKDAppClient import QKDAppClient


class _Resource(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.context_client = ContextClient()
        self.qkd_app_client = QKDAppClient()

class Index(_Resource):
    def get(self):
        return {'hello': 'world'}

class CreateQKDApp(_Resource):
    # Optare: Post request for the QKD Node to call the TeraflowSDN. Example of requests below
    def post(self):
        app = request.get_json()['app']

        devices = self.context_client.ListDevices(Empty())
        devices = devices.devices

        local_device = None


        # This for-loop won't be necessary if we can garantee Device ID is the same as QKDN Id
        for device in devices:
            for config_rule in device.device_config.config_rules:
                if config_rule.custom.resource_key == '__node__':
                    value = json.loads(config_rule.custom.resource_value)
                    qkdn_id = value['qkdn_id']
                    if app['local_qkdn_id'] == qkdn_id:
                        local_device = device
                    break

        # Optare: Todo:  Verify that a service is present for this app
        '''
        requests.post('http://10.211.36.220/app/create_qkd_app', json={'app': {'server_app_id':'1', 'client_app_id':[], 'app_status':'ON', 'local_qkdn_id':'00000001-0000-0000-0000-000000000000', 'backing_qkdl_id':['00000003-0002-0000-0000-000000000000']}})


        requests.post('http://10.211.36.220/app/create_qkd_app', json={'app': {'server_app_id':'1', 'client_app_id':[], 'app_status':'ON', 'local_qkdn_id':'00000003-0000-0000-0000-000000000000', 'backing_qkdl_id':['00000003-0002-0000-0000-000000000000']}})
        '''
        

        if local_device is None:
            return {"status": "fail"}

        external_app_src_dst = {
            'app_id': {'context_id': {'context_uuid': {'uuid': DEFAULT_CONTEXT_NAME}}, 'app_uuid': {'uuid': ''}},
            'app_status': 'QKDAPPSTATUS_' + app['app_status'],
            'app_type': QKDAppTypesEnum.QKDAPPTYPES_CLIENT,
            'server_app_id': app['server_app_id'],
            'client_app_id': app['client_app_id'],
            'backing_qkdl_id': [{'qkdl_uuid': {'uuid': qkdl_id}} for qkdl_id in app['backing_qkdl_id']],
            'local_device_id': local_device.device_id,
            'remote_device_id': {'device_uuid': {'uuid': ''}},
        }


        # Optare: This will call our internal RegisterApp which supports the creation of both internal and external app.
        # Optare the verification for knowing if two parties are requesting the same app is done inside RegisterApp's function
        self.qkd_app_client.RegisterApp(App(**external_app_src_dst))

        # Optare: Todo: Communicate by SBI with both Nodes of the new App

        return {"status": "success"}
