/*
 * NOTICE:  This file is owned by the chat and messaging team (#chat-and-messaging on slack)
 * If you make changes to this file or any of its chat-effecting dependencies, you must do the following two things:
 * 1)  Test chat and whispers in a staging environment
 * 2)  Get a PR approved by a member of the chat and messaging team
 *
 * Thanks!
 */

/* globals */

import Service from 'ember-service';

import Ember from 'ember';
import PubsubDriver from 'pubsub-js-client/PubsubDriver';
import ENV from 'web-client/config/environment';
import run from 'ember-runloop';

const { Evented, Logger, inject } = Ember;

export default Service.extend(Evented, {
  session: inject.service(),

  hasDisconnected: false,
  messageHandlers: {},

  init() {
    this._super(...arguments);
    this.chatTopics = null;
  },

  setupService(roomID, setupCallback) {
    this.get('session').withCurrentUser(userData => {
      if (this.isDestroyed) { return; }
      let pubsub = this._pubsub();
      let oauthToken = userData.chat_oauth_token;
      let userID = userData.id;
      this.chatTopics = [`chat_message_updated.${roomID}`,`chat_moderator_actions.${userID}.${roomID}`];
      for (let i = 0; i < this.chatTopics.length; i++) {
        let chatTopic = this.chatTopics[i];
        let messageHandlers = this.get('messageHandlers');
        messageHandlers[chatTopic] = run.bind(this, this._onPubsubMessage);

        pubsub.Listen({
          topic: chatTopic,
          auth: oauthToken,
          success: function () {
          },
          failure: (err) => {
            Logger.error(`Failed to listen to chat topic: `, chatTopic, err);
          },

          message: messageHandlers[chatTopic]
        });
      }

      pubsub.on('connected', run.bind(this, this._onPubsubConnect));
      pubsub.on('disconnected', run.bind(this, this._onPubsubDisconnect));
      setupCallback();
    });
  },

  tearDownService() {
    if (!this.chatTopics) {
      return; // nothing to do
    }
    let pubsub = this._pubsub();
    for (let i = 0; i < this.chatTopics.length; i++) {
      let chatTopic = this.chatTopics[i];
      let messageHandlers = this.get('messageHandlers');
      pubsub.Unlisten({
        topic: chatTopic,
        success() {
          delete messageHandlers[chatTopic];
        },
        failure: (e) => {
          Logger.error(`Failed to unlisten to chat topic: `, chatTopic, e);
        },
        message: messageHandlers[chatTopic]
      });
    }
    this.chatTopics = null;
  },
  willDestroy() {
    this.tearDownService();
    this._super(...arguments);
  },

  _pubsub() {
    return PubsubDriver.getInstance(ENV.pubsub.environment);
  },

  _onPubsubConnect() {
    if (this.isDestroyed) { return; }
    if (this.get('hasDisconnected')) {
      this.trigger("reconnecting");
      this.set('hasDisconnected', false);
    }
  },

  _onPubsubDisconnect() {
    if (this.isDestroyed) { return; }
    this.set('hasDisconnected', true);
  },

  _onPubsubMessage(payload) {
    if (this.isDestroyed) { return; }
    let json = JSON.parse(payload);
    let type = json.type;
    let parsed = json.data;
    if (type === "message_risk") {
      this.trigger("message_risk", parsed);
    }
    if (parsed.type === "chat_channel_moderation") {
      this.trigger("chat_channel_moderation", parsed);
    }
    if (parsed.type === "chat_login_moderation") {
      this.trigger("chat_login_moderation", parsed);
    }
    if (parsed.type === "twitchbot_message_approval") {
      this.trigger("twitchbot_message_approval", parsed);
    }
    if (parsed.type === "twitchbot_message_denial") {
      this.trigger("twitchbot_message_denial", parsed);
    }
  }
});
