import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
import { BehaviorSubject } from "rxjs";
import { pushBridge } from "./index";

const {
  registerTags: _registerTags,
  unregisterTags: _unregisterTags,
  getRegisteredTags: _getRegisteredTags,
} = pushBridge;

import { bridgeLogger } from "../logger";

export const { log_verbose, log_debug, log_warning, log_info, log_error } =
  createLogger({
    category: "PushTopicManager",
    subsystem: "zapp-react-native-bridge",
    parent: bridgeLogger,
  });

export enum PushTopicManagerConsts {
  PushTopicManagerSubscriptionID = "PushTopicManager",
  PushTopicManagerSource = "PushProvider",
}

export enum PushTopicManagerEvents {
  push_topics_changed = "push_topics_changed",
  plugin_enabled = "plugin_enabled",
  plugin_disabled = "plugin_disabled",
}

export class PushTopicManager {
  private registeredTags: string[] | null;
  private pushTopicSubject: BehaviorSubject<string[] | null>;

  constructor() {
    this.pushTopicSubject = new BehaviorSubject(null);
  }

  getEntryObservable = (): BehaviorSubject<string[]> => {
    return this.pushTopicSubject;
  };

  notifyTagsChange = () => {
    this.pushTopicSubject.next(this.registeredTags);
  };

  routeEvent = (event) => {
    if (event.type === "push_topics_changed") {
      this.registeredTags = event.data;
      this.notifyTagsChange();

      log_debug(
        `routeEvent: Updated registered tags: '${this.registeredTags.join(
          ","
        )}'`
      );
    } else {
      log_error(`routeEvent: Unknown event received: ${event.type}`);
    }
  };

  prepareTags = async () => {
    try {
      this.registeredTags = await _getRegisteredTags();

      log_debug(
        `prepareTags: Current registered tags: '${this.registeredTags.join(
          ","
        )}'`
      );

      this.notifyTagsChange();
    } catch (error) {
      log_error(`prepareTags: Error while preparing tags: ${error.message}`, {
        error,
      });

      throw error;
    }
  };

  registerTags = async (tags: string[]) => {
    try {
      log_debug(
        `registerTags: Native code will register new tags: '${tags.join(",")}'`
      );

      await _registerTags(tags);

      this.registeredTags = this.registeredTags.concat(tags);

      log_debug(
        `registerTags: Tags were successfully registered. New list of existing tags: '${this.registeredTags.join(
          ","
        )}'. Notify subscribers`
      );

      this.notifyTagsChange();
    } catch (error) {
      log_error(
        `registerTags: Error while registering tags: ${error.message}`,
        { error }
      );

      throw error;
    }
  };

  unregisterTags = async (tags: string[]) => {
    try {
      log_debug(
        `unregisterTags: Native code will unregister new tags: '${tags.join(
          ","
        )}'`
      );

      await _unregisterTags(tags);

      this.registeredTags = this.registeredTags.filter(
        (tag) => !tags.includes(tag)
      );

      log_debug(
        `unregisterTags: Tags were successfully unregistered. New list of existing tags: '${this.registeredTags.join(
          ","
        )}'. Notify subscribers`
      );

      this.notifyTagsChange();
    } catch (error) {
      log_error(
        `unregisterTags: Error while unregistering tags: ${error.message}`,
        { error }
      );

      throw error;
    }
  };

  getRegisteredTags = () => {
    return this.registeredTags;
  };

  private static instance: PushTopicManager;
  public static getInstance() {
    if (!PushTopicManager.instance) {
      PushTopicManager.instance = new PushTopicManager();
    }

    return PushTopicManager.instance;
  }
}
