# 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 copy, logging
from typing import Optional, Set
from common.Constants import DEFAULT_CONTEXT_UUID
from common.proto.context_pb2 import Empty
from context.client.ContextClient import ContextClient

LOGGER = logging.getLogger(__name__)

class OwnDomainFinder:
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(OwnDomainFinder, cls).__new__(cls)
        return cls.instance

    def __init__(self) -> None:
        self.__context_client = ContextClient()
        self.__own_domain_uuid : Optional[str] = None
        self.__existing_context_uuids : Optional[Set[str]] = None

    def __update(self) -> None:
        existing_context_ids = self.__context_client.ListContextIds(Empty())
        existing_context_uuids = {context_id.context_uuid.uuid for context_id in existing_context_ids.context_ids}

        # Detect local context name (will be used as abstracted device name); exclude DEFAULT_CONTEXT_UUID
        existing_non_admin_context_uuids = copy.deepcopy(existing_context_uuids)
        existing_non_admin_context_uuids.discard(DEFAULT_CONTEXT_UUID)
        if len(existing_non_admin_context_uuids) != 1:
            MSG = 'Unable to identify own domain name. Existing Contexts({:s})'
            raise Exception(MSG.format(str(existing_context_uuids)))
        
        self.__own_domain_uuid = existing_non_admin_context_uuids.pop()
        self.__existing_context_uuids = existing_context_uuids

    @property
    def own_domain_uuid(self) -> Optional[str]:
        if self.__own_domain_uuid is None: self.__update()
        return self.__own_domain_uuid

    @property
    def existing_context_uuids(self) -> Optional[Set[str]]:
        if self.__existing_context_uuids is None: self.__update()
        return self.__existing_context_uuids
