/**
 * @mergeTarget
 * @module Src/Managers
 */

import {
  LisioBooleanParameterNames,
  LisioNumericParameterNames,
  LisioParameterNames,
  LisioProfileFactory,
  LisioProfileNames,
  LisioStringParameterNames,
} from "@lisio/lisio-profils";
import { UserController } from "../controllers/user-controller";
import { disableReadingMaskHandler } from "../messages/handlers/disable-reading-mask-handler";
import { disableParameterHandler } from "../messages/handlers/disable-parameter-handler";
import { hidePopinHandler } from "../messages/handlers/hide-popin-handler";
import { initMessageHandler } from "../messages/handlers/init-message-handler";
import { lisioFrontLoadedHandler } from "../messages/handlers/lisio-front-loaded-handler";
import { popupResponseHandler } from "../messages/handlers/popup-response-handler";
import { processEndHandler } from "../messages/handlers/process-end-handler";
import { translatorAPITranslateHandler } from "../messages/handlers/translator-api-handler";
import { dicoAPIHandler } from "../messages/handlers/dico-api-handler";
import { shortcutToHandler } from "../messages/handlers/shortcut-to-handler";
import { disableHandler } from "../messages/handlers/disable-handler";
import { closeReadingModeHandler } from "../messages/handlers/close-reading-mode-handler";
import { ReceivedMessageNames } from "../messages/received-message-names";
import { SentMessageNames } from "../messages/sent-messages-names";
import {
  MessageHandler,
  TranslatorAPIResponsesDatas,
} from "../messages/message-types";
import {
  TranslationController,
  TranslationLanguages,
} from "../controllers/translation/translation-controller";
import { askProfilesHandler } from "../messages/handlers/ask-profiles-handler";
import { closeWidgetHandler } from "../messages/handlers/close-widget-handler";
import { CoreErrorCodes } from "@lisio/lisio-engine";
import { CompressorController } from "../controllers/compressor-controller";
import { encodeProfilesHandler } from "../messages/handlers/encode-profiles-handler";
import { allEncodedHandler } from "../messages/handlers/all-encoded-handler";
import { askForActiveHandler } from "../messages/handlers/ask-for-active-handler";
import { InputManager } from "./input-manager";
import { getDirection } from "../controllers/translation/translation-languages-enum-and-types";

/**
 * Class representing a message manager.\
 * It aims to centralize the logic of message exchange between client script and the widget.\
 * If something need to comunicate with client script it has to use this class.\
 * To execute his responsability this class does :
 *  * Handles and execute each incoming message
 *  * Provides methods for each message which has to be sent
 */
class MessageManager {
  /**
   * Private attribute to store lang iso of the widget
   * @source
   */
  private _langIso: TranslationLanguages = TranslationLanguages.FR;

  /**
   * Private attribute to store real lang iso of the widget
   * @source
   */
  private _flagIso: string = "fr";

  /**
   * Private attribute to store the default flag's iso
   * @source
   */
  private _defaultFlagIso: string = "fr";

  /**
   * Private attribute to store origin of client script
   * @source
   */
  private _originOfMessages?: string;

  /**
   * Private attribute to store origin domain
   * @source
   */
  private _originDomain?: string;

  /**
   * @static
   * Private static attribute to store instance of {@link Src/Managers.MessageManager | MessageManager}
   * @source
   */
  private static _current: MessageManager;

  /**
   * Getter for attribute {@link _originOfMessages | _originOfMessages}
   * @returns Returns _originOfMessages attribute
   * @source
   */
  public get originOfMessages(): string | undefined {
    return this._originOfMessages;
  }

  /**
   * Getter for attribute {@link originDomain | originDomain}
   * @returns Returns originDomain attribute
   * @source
   */
  public get originDomain(): string | undefined {
    return this._originDomain;
  }

  /**
   * Setter for attribute {@link _langIso | _langIso}
   * @param {TranslationLanguages} value - New value for attribute {@link _langIso | _langIso}
   * @source
   */
  public set langIso(value: TranslationLanguages) {
    this._langIso = value;
  }

  /**
   * Setter for attribute {@link _flagIso | _flagIso}
   * @param {string} value - New value for attribute {@link _flagIso | _flagIso}
   * @source
   */
  public set flagIso(value: string) {
    this._flagIso = value;
  }

  /**
   * Getter for attribute {@link _flagIso | _flagIso}
   * @returns Returns _flagIso attribute
   * @source
   */
  public get flagIso() {
    return this._flagIso;
  }

  /**
   * Setter for attribute {@link _defaultFlagIso | _defaultFlagIso}
   * @param {string} value - New value for attribute {@link _defaultFlagIso | _defaultFlagIso}
   * @source
   */
  public set defaultFlagIso(value: string) {
    this._defaultFlagIso = value;
  }

  /**
   * Getter for attribute {@link _defaultFlagIso | _defaultFlagIso}
   * @returns Returns _defaultFlagIso attribute
   * @source
   */
  public get defaultFlagIso() {
    return this._defaultFlagIso;
  }

  /**
   * Setter for attribute {@link _originOfMessages | _originOfMessages}
   * @param {string} value - New value for attribute {@link _originOfMessages | _originOfMessages}
   * @source
   */
  public set originOfMessages(value: string) {
    this._originOfMessages = value;
  }

  /**
   * Setter for attribute {@link _originDomain | _originDomain}
   * @param {string} value - New value for attribute {@link _originDomain | _originDomain}
   * @source
   */
  public set originDomain(value: string) {
    this._originDomain = value;
  }

  /**
   * @static
   * Getter for attribute {@link _current | _current}
   * @returns Returns _current attribute
   * @source
   */
  public static get current(): MessageManager {
    return MessageManager._current;
  }

  /**
   * Private attribute to store all message handlers by message name
   * @source
   */
  private _messageHandlers: Map<ReceivedMessageNames, MessageHandler> = new Map<
    ReceivedMessageNames,
    MessageHandler
  >([
    [ReceivedMessageNames.INIT_BACK, initMessageHandler.bind(this)],
    [ReceivedMessageNames.ASK_PROFILS, askProfilesHandler.bind(this)],
    [ReceivedMessageNames.POPUP_RESPONSE, popupResponseHandler.bind(this)],
    [ReceivedMessageNames.DISABLE, disableHandler.bind(this)],
    [
      ReceivedMessageNames.TRANSLATOR_API_TRANSLATE,
      translatorAPITranslateHandler.bind(this),
    ],
    [ReceivedMessageNames.DICO_API, dicoAPIHandler.bind(this)],
    [
      ReceivedMessageNames.DISABLE_READING_MASK,
      disableReadingMaskHandler.bind(this),
    ],
    [
      ReceivedMessageNames.DISABLE_PARAMETER,
      disableParameterHandler.bind(this),
    ],
    [ReceivedMessageNames.HIDE_POPIN, hidePopinHandler.bind(this)],
    [ReceivedMessageNames.PROCESS_END, processEndHandler.bind(this)],
    [
      ReceivedMessageNames.LISIO_FRONT_LOADED,
      lisioFrontLoadedHandler.bind(this),
    ],
    [ReceivedMessageNames.SHORTCUT_TO, shortcutToHandler.bind(this)],
    [ReceivedMessageNames.ENCODE_PROFILES, encodeProfilesHandler.bind(this)],
    [ReceivedMessageNames.ALL_ENCODED, allEncodedHandler.bind(this)],
    [ReceivedMessageNames.ASK_FOR_ACTIVE, askForActiveHandler.bind(this)],
    [
      ReceivedMessageNames.CLOSE_READING_MODE,
      closeReadingModeHandler.bind(this),
    ],
    [ReceivedMessageNames.CLOSE_WIDGET, closeWidgetHandler.bind(this)],
  ]);

  public get messageHandlers() {
    return this._messageHandlers;
  }

  private _channels: Map<string, chrome.runtime.Port> = new Map<
    string,
    chrome.runtime.Port
  >();

  /**
   * Private method to send message with pre-configured datas and origin
   * @param {SentMessageNames} messageName - Message name to sent, reffer to : {@link Src/Messages/Sent.SentMessageNames | SentMessageNames}
   * @param {string} datas - Stringified datas to send to client script
   * @returns Returns nothing
   * @source
   */
  private sendMessage(
    messageName: SentMessageNames,
    datas: string,
    target: string,
  ): void {
    if (__BUILD_TARGET__ === "extension") {
      chrome.storage.local.get("is-reading-mode").then((value) => {
        const isReadingMode = value["is-reading-mode"];
        if (isReadingMode) {
          let panelChannel = this._channels.get("sidepanel-channel");
          if (panelChannel == undefined) {
            panelChannel = chrome.runtime.connect(chrome.runtime.id, {
              name: "sidepanel-channel",
            });
            // panelChannel.postMessage("ça compte quand même que pour un !");
            this._channels.set("sidepanel-channel", panelChannel);
          }
          panelChannel?.postMessage({
            name: "redirect_to_panel",
            datas: JSON.stringify({ name: messageName, datas }),
          });
        } else {
          const backChannel = this._channels.get("channel-back");
          backChannel?.postMessage({
            name: "redirect_to_front",
            datas: JSON.stringify({ name: messageName, datas }),
          });
        }
      });
    } else {
      window.parent.postMessage(
        {
          name: messageName,
          datas: datas,
          target,
        },
        this._originOfMessages == undefined ? "*" : this._originOfMessages,
      );
    }
  }

  /**
   * Public method to attach event listener on window for message.\
   * When a message is catch, his corresponding handler is searched in {@link _messageHandlers | _messageHandlers}.\
   * If a handler is found then the handler is called with datas else nothing is done
   * @returns Returns nothing
   * @source
   */
  public initialize(): void {
    if (__BUILD_TARGET__ === "extension") {
      const backChannel = chrome.runtime.connect(chrome.runtime.id, {
        name: "channel-back",
      });
      // backChannel.postMessage("Legolas que voient vos yeux d'elfe !");
      this._channels.set("channel-back", backChannel);
      backChannel.onMessage.addListener(
        (datas: { name: ReceivedMessageNames; datas: string }) => {
          const message: { name: ReceivedMessageNames; datas: string } = datas;
          if (message.name == undefined) {
            throw new Error("Message name is not defined");
          } else {
            const handler = this._messageHandlers.get(message.name);
            if (handler != undefined) {
              handler(message.datas);
            }
          }
        },
      );
    } else {
      window.addEventListener("message", async (event) => {
        const eventDatas = event.data;
        const handler = this._messageHandlers.get(
          eventDatas.name as ReceivedMessageNames,
        );
        if (handler != undefined) {
          handler(eventDatas.datas);
        }
      });
    }
  }

  /**
   * Public method to send boolean parameter to client script for adapt the website.\
   * This method uses {@link Src/Messages/Sent.SentMessageNames.FEATURE | SentMessageNames.FEATURE} message name
   * @param {LisioBooleanParameterNames} name - Name of the parameter to adapt
   * @param {boolean} value - Indicates the current value of the parameter
   * @returns Returns nothing
   * @source
   */
  public booleanParameterAdaptMessage(
    name: LisioBooleanParameterNames,
    value: boolean,
  ): void {
    if (name === LisioBooleanParameterNames.SPEECH_SYNTHESIS_STATE) {
      this.sendMessage(
        SentMessageNames.FEATURE,
        JSON.stringify({
          feature: name,
          value: value,
          defaultValue: false,
          isReallyActive: InputManager.current.isReallyActive(),
          isConfigured: InputManager.current.isReallyConfigured(),
        }),
        "full",
      );
    } else {
      if (name === LisioBooleanParameterNames.IS_ACTIVE) {
        this._flagIso = this._defaultFlagIso;
        this.sendTranslationLanguageChangeMessage();
      }
      this.sendMessage(
        SentMessageNames.FEATURE,
        JSON.stringify({
          feature: name,
          value: value,
          defaultValue: false,
          dir: getDirection(this._langIso),
          isReallyActive: InputManager.current.isReallyActive(),
          isConfigured: InputManager.current.isReallyConfigured(),
        }),
        "full",
      );
    }
  }

  /**
   * Public method to send string parameter to client script for adapt the website.\
   * This method uses {@link Src/Messages/Sent.SentMessageNames.FEATURE | SentMessageNames.FEATURE} message name
   * @param {LisioStringParameterNames} name - Name of the parameter to adapt
   * @param {string} value - Indicates the current value of the parameter
   * @param {string} defaultValue - Indicates the default value of the parameter
   * @returns Returns nothing
   * @source
   */
  public stringParameterAdaptMessage(
    name: LisioStringParameterNames,
    value: string,
    defaultValue: string,
  ): void {
    this.sendMessage(
      SentMessageNames.FEATURE,
      JSON.stringify({
        feature: name,
        value: value,
        defaultValue: defaultValue,
        isReallyActive: InputManager.current.isReallyActive(),
        isConfigured: InputManager.current.isReallyConfigured(),
      }),
      "full",
    );
  }

  /**
   * Public method to send numeric parameter to client script for adapt the website.\
   * This method uses {@link Src/Messages/Sent.SentMessageNames.FEATURE | SentMessageNames.FEATURE} message name
   * @param {LisioNumericParameterNames} name - Name of the parameter to adapt
   * @param {number} value - Indicates the current value of the parameter
   * @param {number} defaultValue - Indicates the default value of the parameter
   * @returns Returns nothing
   * @source
   */
  public numberParameterAdaptMessage(
    name: LisioNumericParameterNames,
    value: number,
    defaultValue: number,
  ): void {
    this.sendMessage(
      SentMessageNames.FEATURE,
      JSON.stringify({
        feature: name,
        value: value,
        defaultValue: defaultValue,
        isReallyActive: InputManager.current.isReallyActive(),
        isConfigured: InputManager.current.isReallyConfigured(),
      }),
      "full",
    );
  }

  /**
   * Public method to send all parameters of the profile to client script for adapt the website.\
   * This method uses {@link Src/Messages/Sent.SentMessageNames.FEATURE | SentMessageNames.FEATURE} message name
   * @param {LisioProfileNames} name - Name of the profile to adapt
   * @param {boolean} value - Indicates the current value of the profile
   * @returns Returns nothing
   * @source
   */
  public profileAdaptMessage(name: LisioProfileNames, value: boolean): void {
    const profile = LisioProfileFactory.current.buildLisioProfile(
      name as LisioProfileNames,
    );
    const bulk = [];
    for (const parameter of profile.parameters.values()) {
      const finalParameterValue: unknown =
        typeof parameter.value === "boolean"
          ? value
          : typeof parameter.value === "string"
            ? value
              ? parameter.value
              : "default"
            : typeof parameter.value === "number"
              ? value
                ? parameter.value
                : parameter.defaultValue
              : undefined;
      if (
        UserController.current.currentUser != undefined &&
        parameter.name === LisioBooleanParameterNames.BOOK_PAGE &&
        !value &&
        (UserController.current.currentUser.customParameters.has(
          LisioBooleanParameterNames.BOOK_PAGE,
        ) ||
          UserController.current.currentUser?.checkIfParametersAreInActivatedProfile(
            [LisioBooleanParameterNames.BOOK_PAGE],
          ).length > 0)
      ) {
        return;
      }
      if (
        (
          [
            LisioBooleanParameterNames.BOOK_PAGE,
            LisioBooleanParameterNames.READING_MODE,
            LisioNumericParameterNames.FONT_SIZE,
          ] as LisioParameterNames[]
        ).includes(parameter.name)
      ) {
        bulk.unshift({
          feature: parameter.name,
          value: finalParameterValue,
          defaultValue: parameter.defaultValue,
        });
      } else {
        bulk.push({
          feature: parameter.name,
          value: finalParameterValue,
          defaultValue: parameter.defaultValue,
        });
      }
    }
    this.sendMessage(
      SentMessageNames.BULK_FEATURES,
      JSON.stringify({
        bulk,
        isReallyActive: InputManager.current.isReallyActive(),
        isConfigured: InputManager.current.isReallyConfigured(),
      }),
      "full",
    );
  }

  public sendEcoModeState(state: boolean) {
    this.sendMessage(
      SentMessageNames.ECO_MODE,
      JSON.stringify({ state }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.INIT_FRONT | SentMessageNames.INIT_FRONT} to client script.\
   * Notifies client script it can initialize
   * @returns Returns nothing
   * @source
   */
  public sendInitFrontMesssage(): void {
    this.sendMessage(
      SentMessageNames.INIT_FRONT,
      JSON.stringify({
        adaptation: InputManager.current.isReallyActive(),
        isConfigured: InputManager.current.isReallyConfigured(),
      }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.TRANSLATION_LANGUAGE_CHANGE | SentMessageNames.TRANSLATION_LANGUAGE_CHANGE} to client script.\
   * Notifies client script the translation language changed
   * @returns Returns nothing
   * @source
   */
  public sendTranslationLanguageChangeMessage(): void {
    if (
      /*UserController.current.currentUser && UserController.current.currentUser?.customParameters.get(LisioBooleanParameterNames.IS_ACTIVE) && UserController.current.currentUser?.customParameters.get(LisioBooleanParameterNames.SPEECH_SYNTHESIS_STATE) &&*/ UserController.current.currentUser?.customParameters.get(
        LisioBooleanParameterNames.IS_ACTIVE,
      )?.value === true &&
      UserController.current.currentUser?.customParameters.get(
        LisioBooleanParameterNames.SPEECH_SYNTHESIS_STATE,
      )?.value === true
    ) {
      this.sendMessage(
        SentMessageNames.TRANSLATION_LANGUAGE_CHANGE,
        JSON.stringify({
          flagIso: this._flagIso,
          dir: getDirection(this._langIso),
        }),
        "full",
      );
    } else {
      this.sendMessage(
        SentMessageNames.TRANSLATION_LANGUAGE_CHANGE,
        JSON.stringify({
          flagIso: this._flagIso,
          translation: undefined,
          dir: getDirection(this._langIso),
        }),
        "full",
      );
    }
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.DISABLE_ALL | SentMessageNames.DISABLE_ALL} to client script.\
   * Notifies client script to clear all his adaptations and return to a default state
   * @returns Returns nothing
   * @source
   */
  public sendDisableAllMessage(): void {
    this.sendMessage(SentMessageNames.DISABLE_ALL, JSON.stringify({}), "full");
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.TRANS_BANNER_POPUP | SentMessageNames.TRANS_BANNER_POPUP} to client script.\
   * Transmits next translations to client script :
   *  * Title of booke page popup
   *  * Text for "yes button" of book page popup
   *  * Text for "no button" of book page popup
   *  * Text for "close button" of book page popup
   *  * Text of disable banner
   * @returns Returns nothing
   * @source
   */
  public sendTransBannerPopupMessage(
    descriptionId: string,
    parameterName:
      | LisioBooleanParameterNames.BOOK_PAGE
      | LisioBooleanParameterNames.READING_MODE,
    triggererId: string,
  ): void {
    this.sendMessage(
      SentMessageNames.TRANS_BANNER_POPUP,
      JSON.stringify({
        confirmationModalDescription:
          TranslationController.current.getTranslation(
            `infobox-${descriptionId}`,
          ),
        confirmationModalParameter: parameterName,
        confirmationModalWidgetTriggererFocus: triggererId,
      }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.TRANSLATOR_API_TRANSLATE_RESPONSE | SentMessageNames.TRANSLATOR_API_TRANSLATE_RESPONSE} to client script.\
   * Transmits to client scripts results of translator api
   * @returns Returns nothing
   * @source
   */
  public sendTranslatorAPITranslateResponseMessage(
    keyHandler: string,
    textObjs: TranslatorAPIResponsesDatas,
  ): void {
    this.sendMessage(
      SentMessageNames.TRANSLATOR_API_TRANSLATE_RESPONSE,
      JSON.stringify({
        keyHandler: keyHandler,
        texts: textObjs,
      }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.DICO_API_RESPONSE | SentMessageNames.DICO_API_RESPONSE} to client script.\
   * Transmits to client scripts results of dico api
   * @returns Returns nothing
   * @source
   */
  public sendDicoAPIResponseMessage(
    textObjs: TranslatorAPIResponsesDatas,
  ): void {
    this.sendMessage(
      SentMessageNames.DICO_API_RESPONSE,
      JSON.stringify({
        word: textObjs,
      }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.PROFILS_RESPONSE | SentMessageNames.PROFILS_RESPONSE} to client script.\
   * Transmits to client scripts all users
   * @returns Returns nothing
   * @source
   */
  public sendProfilesResponseMessage(): void {
    this.sendMessage(
      SentMessageNames.PROFILS_RESPONSE,
      JSON.stringify(UserController.current.users),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.ENCODE_PROFILES_RESPONSE | SentMessageNames.ENCODE_PROFILES_RESPONSE} to client script.\
   * Transmits to client scripts all encoded users
   * @returns Returns nothing
   * @source
   */
  public sendEncodeProfilesResponseMessage(): void {
    const usernames = JSON.stringify(UserController.current.usernames);
    const formatedUsers = [];
    for (const user of UserController.current.users.values()) {
      formatedUsers.push(user.formatForSaving());
    }
    this.sendMessage(
      SentMessageNames.ENCODE_PROFILES_RESPONSE,
      JSON.stringify(
        `lisioUsernames${encodeURIComponent(
          `=${btoa(usernames)}`,
        )}&lisioUsers${encodeURIComponent(
          `=${CompressorController.current.encodeUsers(formatedUsers)}`,
        )}`,
      ),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.ALL_ENCODED_RESPONSE | SentMessageNames.ALL_ENCODED_RESPONSE} to client script.\
   * Transmits to client scripts all datas
   * @param {string} encoded - Encoded datas
   * @returns Returns nothing
   * @source
   */
  public sendAllEncodedResponseMessage(encoded: string): void {
    this.sendMessage(SentMessageNames.ALL_ENCODED_RESPONSE, encoded, "full");
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.READING_MODE_RESPONSE | SentMessageNames.READING_MODE_RESPONSE} to client script.\
   * Transmits to client scripts to start reading mode
   * @returns Returns nothing
   * @source
   */
  public sendReadingModeResponseMessage(): void {
    this.sendMessage(
      SentMessageNames.READING_MODE_RESPONSE,
      JSON.stringify({}),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.NEW_TAB | SentMessageNames.NEW_TAB} to client script.\
   * Notifies client scripts that it need to navigate to a new url
   * @param {string} url - URL to navigate to
   * @param {boolean} ecoOrRural - Notifies if eco or rural are enabled
   * @param {boolean} same - Notifies if have to open a new tab or not
   * @param {string} urlQuery - Transmits a query string to add in URL
   * @returns Returns nothing
   * @source
   */
  public sendNewTabMessage(
    url: string,
    ecoOrRural: boolean = false,
    same: boolean,
    urlQuery: string,
  ): void {
    this.sendMessage(
      SentMessageNames.NEW_TAB,
      JSON.stringify({
        url,
        ecoOrRural,
        same,
        urlQuery,
      }),
      "full",
    );
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.CLOSE_WIDGET | SentMessageNames.CLOSE_WIDGET} to client script.\
   * Notifies client script to close the widget
   * @returns Returns nothing
   * @source
   */
  public sendCloseWidgetMessage(): void {
    if (__BUILD_TARGET__ === "extension") {
      // for(const popup of chrome.extension.getViews({type: 'popup'})){
      //   popup.close();
      // }
      window.close();
    } else {
      this.sendMessage(
        SentMessageNames.CLOSE_WIDGET,
        JSON.stringify({}),
        "full",
      );
    }
  }

  /**
   * Public method to send {@link Src/Messages/Sent.SentMessageNames.ACTIVE_RESPONSE | SentMessageNames.ACTIVE_RESPONSE} to client script.\
   * Notifies client script is user active
   * @returns Returns nothing
   * @source
   */
  public sendActiveResponseMessage(): void {
    this.sendMessage(
      SentMessageNames.ACTIVE_RESPONSE,
      JSON.stringify({
        value: InputManager.current.isReallyActive(),
        defaultValue: false,
        isConfigured: InputManager.current.isReallyConfigured(),
      }),
      "full",
    );
  }

  /**
   * Constructor of class {@link MessageManager | MessageManager}
   * @throws If singleton already initialize.\
   * See {@link https://env-preprod-docs.lisio.fr/lisio-engine/enums/Src_Core.CoreErrorCodes.html#SINGLETON_NOT_UNIQUE | CoreErrorCodes.SINGLETON_NOT_UNIQUE}
   * @source
   */
  constructor() {
    if (MessageManager._current == undefined) {
      MessageManager._current = this;
      this.initialize();
    } else {
      throw new Error(
        `Code : ${CoreErrorCodes.SINGLETON_NOT_UNIQUE}. Singleton already initialize`,
      );
    }
  }
}

export { MessageManager };
