"""Spamcheck queue used to emit spam verdicts"""
from threading import Thread

from google.cloud import pubsub_v1
from google.api_core.exceptions import AlreadyExists
from vyper import v

from app import logger
from app.event import Event

log = logger.logger

queues = set()

class Queue:
    """Base class for Queue implementation. Specific queues should inherit from this class."""
    def enabled(self) -> bool:
        """Determine if a queue is enabled."""
        raise NotImplementedError("Queue not implemented")

    def publish(self, event: Event) -> None:
        """Publish an event to the queue.

        Args:
            event (Event): The Event to publish.
        """
        raise NotImplementedError("Queue not implemented")

class GooglePubSub(Queue):
    """Implementation of the Gooogle PubSub message queue."""

    project_key = "google_pubsub_project"
    topic_key = "google_pubsub_topic"

    def __init__(self):
        self._enabled = False
        if not v.is_set(self.project_key):
            log.debug("Google PubSub disabled")
            return
        project = v.get_string(self.project_key)
        topic = v.get_string(self.topic_key)

        self.publisher = pubsub_v1.PublisherClient()
        self.topic = self.publisher.topic_path(project, topic)
        try:
            self.publisher.create_topic(name=self.topic)
        except AlreadyExists:
            pass
        except Exception as exp: # pylint: disable=broad-except
            log.error(f"Failed to initialize Google PubSub: {exp}")
            return

        log.debug("Google PubSub enabled")
        self._enabled = True

    def enabled(self) -> bool:
        return self._enabled

    def publish(self, event: Event) -> None:
        if self.enabled():
            try:
                future = self.publisher.publish(self.topic, event.json())
                future.result()
            except Exception as exp: # pylint: disable=broad-except
                log.error(f"Google PubSub error: {exp}")

google_pubsub = GooglePubSub()
if google_pubsub.enabled():
    queues.add(google_pubsub)

def publish(event: Event) -> None:
    """Publish an event to all configured queues."""
    for queue in queues:
        thread = Thread(target=queue.publish, args=(event,))
        thread.daemon = True
        thread.start()
