/**
 * Applies attributes to the chat container for channels.
 * @module Chat
 * @memberof Builtin.Attributes.Chat
 */

import { isString, toKebabCase } from '@vizality/util/string';
import { getOwnerInstance } from '@vizality/util/react';
import { waitForElement } from '@vizality/util/dom';
import { patch, unpatch } from '@vizality/patcher';
import { getModule } from '@vizality/webpack';

/**
 * Discord channel types.
 * @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-types|Discord}
 */
const CHANNEL_TYPES = {};
for (const type of Object.entries($discord.constants.ChannelTypes)) {
  if (isString(type[1])) {
    [ , CHANNEL_TYPES[Number(type[0])] ] = type;
  }
}

export const labels = [ 'Chat' ];

export default async builtin => {
  const { chat } = getModule('chat');
  const instance = getOwnerInstance(await waitForElement(`.${chat?.split(' ')[0]}`));
  patch('vz-attributes-chat', instance?.__proto__, 'render', function (_, res) {
    try {
      if (!res.props?.children?.[1]?.props || !this?.props?.channel) {
        return;
      }

      const { channel, guild } = this.props;

      /**
       * Set some special attributes depending on some properties.
       */
      res.props.children[1].props['vz-rules'] = Boolean(guild?.rulesChannelId === channel.id) && '';
      res.props.children[1].props['vz-nsfw'] = Boolean(channel.nsfw) && '';

      /**
       * Sets an attribute for special types of messages.
       */
      res.props.children[1].props['vz-channel-type'] = toKebabCase(CHANNEL_TYPES[channel.type]);

      const attributes = {
        'vz-search-results-active': this.props.section === 'SEARCH',
        'vz-message-editing-active': this.props.isEditing,
        'vz-voice-call-active': this.props.inCall,
        'vz-video-call-active': this.props.hasVideo,
        'vz-modal-active': this.props.hasModalOpen
      };

      /**
       * Add and remove the attributes based on true/false.
       */
      const root = document.documentElement;
      const addAttributes = Object.keys(attributes).filter(m => attributes[m]);
      const removeAttributes = Object.keys(attributes).filter(m => !attributes[m]);
      addAttributes.forEach(attr => root.setAttribute(attr, ''));
      removeAttributes.forEach(attr => root.removeAttribute(attr));
    } catch (err) {
      return builtin.error(builtin._labels.concat(labels), err);
    }
  });
  setImmediate(() => instance?.forceUpdate());
  return () => unpatch('vz-attributes-chat');
};
