# SPDX-FileCopyrightText: 2020 The Magma Authors.
# SPDX-FileCopyrightText: 2022 Open Networking Foundation <support@opennetworking.org>
#
# SPDX-License-Identifier: BSD-3-Clause

import abc
import contextlib
import json
import os
from typing import Any, Generic, TypeVar

import configuration.events as magma_configuration_events
from google.protobuf import json_format
from common import serialization_utils
from configuration.exceptions import LoadConfigError
from configuration.mconfigs import (
    filter_configs_by_key,
    unpack_mconfig_any,
)
from orc8r.protos.mconfig_pb2 import GatewayConfigs, GatewayConfigsMetadata

T = TypeVar('T')

MCONFIG_DIR = './magma_configs'
MCONFIG_OVERRIDE_DIR = './override_configs'
DEFAULT_MCONFIG_DIR = os.environ.get('MAGMA_CONFIG_LOCATION', MCONFIG_DIR)


def get_mconfig_manager():
    """
    Get the mconfig manager implementation that the system is configured to
    use.

    Returns: MconfigManager implementation
    """
    # This is stubbed out after deleting the streamed mconfig manager
    return MconfigManagerImpl()


def load_service_mconfig(service: str, mconfig_struct: Any) -> Any:
    """
    Utility function to load the mconfig for a specific service using the
    configured mconfig manager.
    """
    return get_mconfig_manager().load_service_mconfig(service, mconfig_struct)


def load_service_mconfig_as_json(service_name: str) -> Any:
    """
    Loads the managed configuration from its json file stored on disk.

    Args:
        service_name (str): name of the service to load the config for

    Returns: Loaded config value for the service as parsed json struct, not
    protobuf message struct
    """
    return get_mconfig_manager().load_service_mconfig_as_json(service_name)


class MconfigManager(Generic[T]):
    """
    Interface for a class which handles loading and updating some cloud-
    managed configuration (mconfig).
    """

    @abc.abstractmethod
    def load_mconfig(self) -> T:
        """
        Load the managed configuration from its stored location.

        Returns: Loaded mconfig
        """
        pass

    @abc.abstractmethod
    def load_service_mconfig(
        self, service_name: str,
        mconfig_struct: Any,
    ) -> Any:
        """
        Load a specific service's managed configuration.

        Args:
            service_name (str): name of the service to load a config for
            mconfig_struct (Any): protobuf message struct of the managed config
            for the service

        Returns: Loaded config value for the service
        """
        pass

    @abc.abstractmethod
    def load_mconfig_metadata(self) -> GatewayConfigsMetadata:
        """
        Load the metadata of the managed configuration.

        Returns: Loaded mconfig metadata
        """
        pass

    @abc.abstractmethod
    def update_stored_mconfig(self, updated_value: str):
        """
        Update the stored mconfig to the provided serialized value

        Args:
            updated_value: Serialized value of new mconfig value to store
        """
        pass

    @abc.abstractmethod
    def deserialize_mconfig(
        self, serialized_value: str,
        allow_unknown_fields: bool = True,
    ) -> T:
        """
        Deserialize the given string to the managed mconfig.

        Args:
            serialized_value:
                Serialized value of a managed mconfig
            allow_unknown_fields:
                Set to true to suppress errors from parsing unknown fields

        Returns: deserialized mconfig value
        """
        pass

    @abc.abstractmethod
    def delete_stored_mconfig(self):
        """
        Delete the stored mconfig file.
        """
        pass


class MconfigManagerImpl(MconfigManager[GatewayConfigs]):
    """
    Legacy mconfig manager for non-offset mconfigs
    """

    MCONFIG_FILE_NAME = 'gateway.mconfig'
    MCONFIG_PATH = os.path.join(MCONFIG_OVERRIDE_DIR, MCONFIG_FILE_NAME)

    def load_mconfig(self) -> GatewayConfigs:
        cfg_file_name = self._get_mconfig_file_path()
        try:
            with open(cfg_file_name, 'r', encoding='utf-8') as cfg_file:
                mconfig_str = cfg_file.read()
            return self.deserialize_mconfig(mconfig_str)
        except (OSError, json.JSONDecodeError, json_format.ParseError) as e:
            raise LoadConfigError('Error loading mconfig, mconfig may have format issue') from e

    def load_service_mconfig(
        self, service_name: str,
        mconfig_struct: Any,
    ) -> Any:
        mconfig = self.load_mconfig()
        if service_name not in mconfig.configs_by_key:
            raise LoadConfigError(
                "Service ({}) missing in mconfig".format(service_name),
            )

        service_mconfig = mconfig.configs_by_key[service_name]
        return unpack_mconfig_any(service_mconfig, mconfig_struct)

    def load_service_mconfig_as_json(self, service_name) -> Any:
        cfg_file_name = self._get_mconfig_file_path()
        with open(cfg_file_name, 'r', encoding='utf-8') as f:
            json_mconfig = json.load(f)
            service_configs = json_mconfig.get('configsByKey', {})
            service_configs.update(json_mconfig.get('configs_by_key', {}))
        if service_name not in service_configs:
            raise LoadConfigError(
                "Service ({}) missing in mconfig".format(service_name),
            )

        return service_configs[service_name]

    def load_mconfig_metadata(self) -> GatewayConfigsMetadata:
        mconfig = self.load_mconfig()
        return mconfig.metadata

    def deserialize_mconfig(
        self, serialized_value: str,
        allow_unknown_fields: bool = True,
    ) -> GatewayConfigs:
        # First parse as JSON in case there are types unrecognized by
        # protobuf symbol database
        json_mconfig = json.loads(serialized_value)
        cfgs_by_key_json = json_mconfig.get('configs_by_key', {})
        cfgs_by_key_json.update(json_mconfig.get('configsByKey', {}))
        filtered_cfgs_by_key = filter_configs_by_key(cfgs_by_key_json)

        # Set configs to filtered map, re-dump and parse
        if 'configs_by_key' in json_mconfig:
            json_mconfig.pop('configs_by_key')
        json_mconfig['configsByKey'] = filtered_cfgs_by_key
        json_mconfig_dumped = json.dumps(json_mconfig)

        # Workaround for outdated protobuf library on sandcastle
        if allow_unknown_fields:
            return json_format.Parse(
                json_mconfig_dumped,
                GatewayConfigs(),
                ignore_unknown_fields=True,
            )
        else:
            return json_format.Parse(json_mconfig_dumped, GatewayConfigs())

    def delete_stored_mconfig(self):
        with contextlib.suppress(FileNotFoundError):
            os.remove(self.MCONFIG_PATH)
        magma_configuration_events.deleted_stored_mconfig()

    def update_stored_mconfig(self, updated_value: str) -> GatewayConfigs:
        parsed = json.loads(updated_value)
        serialization_utils.write_to_file_atomically(
            self.MCONFIG_PATH, json.dumps(parsed, indent=4, sort_keys=True),
        )
        magma_configuration_events.updated_stored_mconfig()

    def _get_mconfig_file_path(self):
        if os.path.isfile(self.MCONFIG_PATH):
            return self.MCONFIG_PATH
        else:
            return os.path.join(DEFAULT_MCONFIG_DIR, self.MCONFIG_FILE_NAME)
