import { Sib, store, StoreMixin } from 'https://cdn.skypack.dev/@startinblox/core@0.15';
import { Deferred } from './utils.js';
import ComponentPath from './path.js';

import './conversejs/converse.min.js';
import './conversejs/emojis.js';

import './plugins/converse-rai.js';
import './plugins/sib-chat-navigation.js';
import './plugins/sib-custom-hats.js';
import './plugins/sib-disconnected.js';
import './plugins/sib-history-improved.js';
import './plugins/sib-mention-mobile.js';
import './plugins/sib-remove-notifications.js';
import './plugins/sib-reply-to-message.js';
import './plugins/sib-scroll-down-on-focus.js';
import './plugins/sib-subscribe-to-rai.js';

export const SolidXMPPChat = {
  name: 'solid-xmpp-chat',
  use: [StoreMixin],
  attributes: {
    authentication: {
      type: String,
      default: 'login',
    },
    autoLogin: {
      type: Boolean,
      default: true,
    },
    i18n: {
      type: String,
      default: 'fr',
    },
    websocketUrl: {
      type: String,
      default: 'wss://jabber.happy-dev.fr/xmpp-websocket',
    },
  },

  get extra_context() {
    return {
      'foaf': 'http://xmlns.com/foaf/0.1/',
      'chatProfile': 'http://happy-dev.fr/owl/#chatProfile',
      'jabberID': 'foaf:jabberID',
    };
  },

  async created() {
    const check_identified = await document.querySelector('sib-auth').getUserIdToken();
    if (check_identified) {
      this.element.attachShadow({ mode: 'open' });
      this.importCSS(`${ComponentPath}/dist/conversejs/converse.min.css?min`);
      this.importCSS(`${ComponentPath}/dist/index.css?min`);
      if (typeof converse_sib === 'undefined') {
        this.initializeConverse();
      }
    } // Else, not logged in on page load (even if not on chat)
  },

  importCSS(path) {
    let link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = path;
    this.element.shadowRoot.append(link);
  },

  empty() {
    this.element.innerHTML = 'Loading...';
  },

  async populate() {
    if (typeof converse_sib !== 'undefined') {
      await converse_sib.loaded_deferred;
      if (this.resource) {
        if (await this.resource.jabberRoom) {
          this.jid = await this.resource['jabberID'];
        } else {
          this.jid = await this.resource['chatProfile.jabberID'];
          const user = await document.querySelector('sib-auth').getUser();
          const userProfile = await store.getData(user['@id'], this.context);
          const contactsURL = await userProfile['contacts.@id'];
          const contactInterval = setInterval(async () => {
            let retry = false;
            let userContacts = [];
            for (let contact of await userProfile['contacts.ldp:contains']) {
              if (contact) {
                userContacts.push(await contact['contact.@id']);
              } else {
                retry = true;
              }
            }
            if (!retry) {
              clearInterval(contactInterval);
              if (!userContacts.includes(this.resource['@id'])) {
                store.post({
                  'contact': this.resource['@id'],
                  '@context': this.context,
                }, contactsURL);
              }
            }
          }, 100);
        }
        await converse_sib.connected_deferred;

        window.dispatchEvent(new CustomEvent('sib-change-chat', {
          detail: {
            jid: this.jid,
            is_groupchat: await this.resource.jabberRoom,
            root: this.element.shadowRoot,
          },
        }));

        window.dispatchEvent(new CustomEvent('read', {
          detail: {
            resource: {
              '@id': this.resource['@id'],
            },
          },
        }));
      }
    } // Else, not logged in, on chat change
  },

  removeConverseDatabase() {
    for (let key in sessionStorage) {
      if (sessionStorage.hasOwnProperty(key) && /converse/.test(key)) {
        sessionStorage.removeItem(key);
      }
    }
    for (let key in localStorage) {
      if (localStorage.hasOwnProperty(key) && /converse/.test(key)) {
        localStorage.removeItem(key);
      }
    }
    indexedDB.deleteDatabase('converse-persistent');
  },

  initializeConverse() {
    window.converse_sib = {};

    // Deferred resolved at the end of this function
    converse_sib.loaded_deferred = new Deferred();

    // Deferred resolved after converse.initialize
    converse_sib.connected_deferred = new Deferred();

    this.removeConverseDatabase();

    // Initialize deferred resolution plugin
    setTimeout(async () => {

      // Initialize deferred resolution plugin
      converse.plugins.add('sib-connected', {
        initialize() {
          const { api } = this._converse;
          api.listen.on('connectionInitialized', converse_sib.connected_deferred.resolve);
        },
      });

      const user = await document.querySelector('sib-auth').getUser();
      const userProfile = await store.getData(user['@id'], this.context);
      const jabberID = await userProfile['chatProfile.jabberID'];

      if (this.resource) {
        if (await this.resource.jabberRoom) {
          this.jid = await this.resource['jabberID'];
        } else {
          this.jid = await this.resource['chatProfile.jabberID'];
        }
      } else {
        this.jid = jabberID;
      }

      const idToken = await document.querySelector('sib-auth').getUserIdToken();

      converse.initialize({
        'assets_path': (/skypack/.test(ComponentPath) ? ComponentPath.replace('cdn.skypack.dev', 'unpkg.com') : ComponentPath) + '/dist/conversejs/',
        'authentication': this.element.dataset.authentication || 'login',
        'password': idToken,
        'allow_bookmarks': false,
        'allow_chat_pending_contacts': true,
        'allow_message_retraction': 'moderator',
        'allow_non_roster_messaging': true,
        'allow_dragresize': false,
        'allow_logout': false,
        'archived_messages_page_size': '30',
        'auto_list_rooms': true,
        'auto_login': this.element.dataset.autoLogin === 'true',
        'auto_join_on_invite': true,
        'auto_reconnect': true,
        'auto_register_muc_nickname': false,
        'websocket_url': this.element.dataset.websocketUrl || 'wss://jabber.happy-dev.fr/xmpp-websocket',
        'enable_smacks': true,
        'clear_messages_on_reconnection': false,
        'discover_connection_methods': false,
        'jid': jabberID.toLowerCase(),
        'i18n': this.element.dataset.i18n || 'fr',
        'loglevel': 'fatal',
        'message_archiving': 'always',
        'message_archiving_timeout': 60000,
        'muc_disable_slash_commands': true,
        'muc_hats': ['hats', 'vcard_roles', 'admin'],
        'role_affiliation_hat_conversions': { 'admin': 'Administrateur' },
        'muc_nickname_from_jid': false,
        'muc_fetch_members': true,
        'muc_show_info_messages': [],
        'muc_subscribe_to_rai': true,
        'play_sounds': false,
        'root': this.element.shadowRoot,
        'show_client_info': false,
        'show_desktop_notifications': false,
        'persistent_store': 'none',
        'sounds_path': ComponentPath + '/dist/conversejs/',
        'show_send_button': false,
        'view_mode': 'fullscreen',
        'visible_toolbar_buttons': {
          call: false,
          spoiler: false,
          emoji: true,
          fileupload: true, // Not working in current Converse
          toggle_occupants: false,
        },
        'whitelisted_plugins': [
          'converse-rai',
          'sib-chat-navigation',
          'sib-connected',
          'sib-custom-hats',
          'sib-disconnected',
          'sib-history-improved',
          'sib-mention-mobile',
          'sib-remove-notifications',
          'sib-reply-to-message',
          'sib-scroll-down-on-focus',
          'sib-subscribe-to-rai',
        ],
      });

      converse_sib.loaded_deferred.resolve();
    }, 0);
  },
};

Sib.register(SolidXMPPChat);