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

import abc
import logging
import threading
import time
from typing import Any, List

import grpc
import snowflake
from google.protobuf import any_pb2
from common import serialization_utils
from common.metrics import STREAMER_RESPONSES
from common.service_registry import ServiceRegistry
from configuration.service_configs import get_service_config_value
from orc8r.protos.streamer_pb2 import DataUpdate, StreamRequest
from orc8r.protos.streamer_pb2_grpc import StreamerStub


class StreamerClient(threading.Thread):
    """
    StreamerClient provides an interface to communicate with the Streamer
    service in the cloud to get updates for a stream.

    The StreamerClient spawns a thread which listens to updates and
    schedules a callback in the asyncio event loop when an update
    is received from the cloud.

    If the connection to the cloud gets terminated, the StreamerClient
    would retry (TBD: with exponential backoff) to connect back to the cloud.
    """

    class Callback:

        @abc.abstractmethod
        def get_request_args(self, stream_name: str) -> Any:
            """
            This is called before every stream request to collect any extra
            arguments to send up to the cloud streamer service.

            Args:
                stream_name:
                Name of the stream that the request arg will be sent to

            Returns: A protobuf message
            """
            pass

        @abc.abstractmethod
        def process_update(
            self, stream_name: str, updates: List[DataUpdate],
            resync: bool,
        ):
            """
            Called when we get an update from the cloud. This method will
            be called in the event loop provided to the StreamerClient.

            Args:
                stream_name: Name of the stream
                updates: Array of updates
                resync: if true, the application can clear the
                    contents before applying the updates
            """
            raise NotImplementedError()

    def __init__(self, stream_callbacks, loop):
        """
        Args:
            stream_callbacks ({string: Callback}): Mapping of stream names to
            callbacks to subscribe to.
            loop: asyncio event loop to schedule the callback
        """
        threading.Thread.__init__(self)
        self._stream_callbacks = stream_callbacks
        self._loop = loop
        # Set this thread as daemon thread. We can kill this background
        # thread abruptly since we handle all updates (and database
        # transactions) in the asyncio event loop.
        self.daemon = True

        # Don't allow stream update rate faster than every 5 seconds
        self._reconnect_pause = get_service_config_value(
            'streamer', 'reconnect_sec', 60,
        )
        self._reconnect_pause = max(5, self._reconnect_pause)
        logging.info("Streamer reconnect pause: %d", self._reconnect_pause)
        self._stream_timeout = get_service_config_value(
            'streamer', 'stream_timeout', 150,
        )
        logging.info("Streamer timeout: %d", self._stream_timeout)

    def run(self):
        while True:
            try:
                channel = ServiceRegistry.get_rpc_channel(
                    'streamer', ServiceRegistry.CLOUD,
                )
                client = StreamerStub(channel)
                self.process_all_streams(client)
            except Exception as exp:  # pylint: disable=broad-except
                logging.error("Error with streamer: %s", exp)

            # If the connection is terminated, wait for a period of time
            # before connecting back to the cloud.
            # TODO: make this more intelligent (exponential backoffs, etc.)
            time.sleep(self._reconnect_pause)

    def process_all_streams(self, client):
        for stream_name, callback in self._stream_callbacks.items():
            try:
                self.process_stream_updates(client, stream_name, callback)

                STREAMER_RESPONSES.labels(result='Success').inc()
            except grpc.RpcError as err:
                logging.error(
                    "Error! Streaming from the cloud failed! [%s] %s",
                    err.code(), err.details(),
                )
                STREAMER_RESPONSES.labels(result='RpcError').inc()
            except ValueError as err:
                logging.error("Error! Streaming from cloud failed! %s", err)
                STREAMER_RESPONSES.labels(result='ValueError').inc()

    def process_stream_updates(self, client, stream_name, callback):
        extra_args = self._get_extra_args_any(callback, stream_name)
        request = StreamRequest(
            gatewayId=snowflake.snowflake(),
            stream_name=stream_name,
            extra_args=extra_args,
        )
        for update_batch in client.GetUpdates(
                request, timeout=self._stream_timeout,
        ):
            self._loop.call_soon_threadsafe(
                callback.process_update,
                stream_name,
                update_batch.updates,
                update_batch.resync,
            )

    @staticmethod
    def _get_extra_args_any(callback, stream_name):
        extra_args = callback.get_request_args(stream_name)
        if extra_args is None:
            return None
        else:
            extra_any = any_pb2.Any()
            extra_any.Pack(extra_args)
            return extra_any


def get_stream_serialize_filename(stream_name):
    return '/var/opt/magma/streams/{}'.format(stream_name)


class SerializingStreamCallback(StreamerClient.Callback):
    """
    Streamer client callback which decodes stream update as a string and writes
    it to a file, overwriting the previous contents of that file. The file
    location is defined by get_stream_serialize_filename.

    This callback will only save the newest update, with each successive update
    overwriting the previous.
    """

    def get_request_args(self, stream_name: str) -> Any:
        return None

    def process_update(self, stream_name, updates, resync):
        if not updates:
            return
        # For now, we only care about the last (newest) update
        for update in updates[:-1]:
            logging.info('Ignoring update %s', update.key)

        logging.info('Serializing stream update %s', updates[-1].key)
        filename = get_stream_serialize_filename(stream_name)
        serialization_utils.write_to_file_atomically(
            filename,
            updates[-1].value.decode(),
        )
