import { ApplicationContext, LangUtils } from "@sankhyalabs/core";
import messageResourcePtBR from "./messageResourcePtBRUtils";
import messageResourceEnUS from "./messageResourceEnUSUtils";
import messageResourceEsES from "./messageResourceEsESUtils";
export class SnkMessageBuilder {
  constructor(domainName) {
    this._defaults = messageResourcePtBR;
    this._messageResourceEnUS = messageResourceEnUS;
    this._messageResourceEsES = messageResourceEsES;
    this._currentOperation = OperationMap.CLEAN;
    this._domainName = domainName;
    this._application = ApplicationContext.getContextValue("__SNK__APPLICATION__");
    this._lang = LangUtils.getLanguage();
    this.loadAppMessages().then((msgs) => {
      this._appMessages = msgs;
    }, error => {
      console.info('O arquivo de mensagens personalizadas não foi encontrado no caminho /messages/appmessages', error);
    });
  }
  /**
   * Existem mensagens sensíveis a operação. Por exemplo, a mensagem
   * de inclusão pode ser diferente da mensagem de alteração do mesmo
   * recurso. Para isso "currentOperation" pode variar de acordo com
   * OperationMap.
   */
  set currentOperation(op) {
    this._currentOperation = op;
  }
  /**
   * Método usado para se obter mensagens, respeitando o padrão do sistema
   * ou as mensagens específicas de cada tela
   *
   * @param key Chave usada para obter mensagens. Deve-se usar o separador "."
   * alcançar diversos níveis.
   * @param params Quando a mensagem possui o padrão {{NOME}} as ocorrências
   * serão substituidas pelo respectivo valor do param.
   * @returns A mensagem formatada.
   */
  getMessage(key, params) {
    if (key == undefined)
      return undefined;
    var parts = key.split(".");
    let msg = this.resolveMessage(parts, this.getDomainMessages());
    if (msg == undefined) {
      msg = this.getMessagesDefaults(parts);
    }
    if (this.customMessageBuilder) {
      const result = this.customMessageBuilder(key, msg, params);
      msg = result === null || result === void 0 ? void 0 : result.message;
      params = result === null || result === void 0 ? void 0 : result.params;
    }
    return this.postProcess(msg, params);
  }
  /**
   * Retorna o idioma atual configurado na aplicação.
   *
   * @returns {string} O código do idioma atual (por exemplo: 'pt-BR', 'en-US', 'es-ES')
   */
  getLanguageApplication() {
    return this._lang;
  }
  getMessagesDefaults(parts) {
    switch (this._lang) {
      case LangUtils.ELanguages.EN_US:
        return this.resolveMessage(parts, this._messageResourceEnUS);
      case LangUtils.ELanguages.ES_ES:
        return this.resolveMessage(parts, this._messageResourceEsES);
      default:
        return this.resolveMessage(parts, this._defaults);
    }
  }
  getDomainMessages() {
    if (!this._appMessages)
      return undefined;
    if (!this._domainName) {
      return this._appMessages['Global'] || this._appMessages;
    }
    return this._appMessages[this._domainName];
  }
  resolveMessage(keys, object) {
    if (object == undefined) {
      return undefined;
    }
    const key = keys[0];
    const result = object[key];
    if (result) {
      if (this.isOperationSensitive(result)) {
        return result[this._currentOperation];
      }
      else {
        const isLeaf = keys.length === 1 ||
          result == undefined ||
          typeof result === "string";
        return isLeaf ? result : this.resolveMessage(keys.slice(1), result);
      }
    }
  }
  isOperationSensitive(value) {
    return value[OperationMap.CLONE] != undefined ||
      value[OperationMap.INSERT] != undefined ||
      value[OperationMap.UPDATE] != undefined ||
      value[OperationMap.CLEAN] != undefined;
  }
  postProcess(message, params) {
    if (message) {
      const propPattern = /(.*?)\{\{(.+?)\}\}/g;
      let processed = "";
      let tail = message;
      let result;
      while ((result = propPattern.exec(message)) !== null) {
        const [match, head, attribute] = result;
        const tailIndex = result.index + match.length;
        tail = tailIndex < message.length ? message.substring(tailIndex) : "";
        let replacement = params ? params[attribute] : undefined;
        if (replacement == undefined) {
          replacement = "";
        }
        processed += head + replacement;
      }
      return processed + tail;
    }
    else {
      return message;
    }
  }
  async loadAppMessages() {
    const messagesUrl = await this._application.getApplicationPath();
    const langSuffix = (this._lang !== LangUtils.ELanguages.PT_BR) ? `-${this._lang}` : "";
    const fileUrl = `${messagesUrl}/messages/appmessages${langSuffix}.js`;
    const response = await fetch(fileUrl);
    if (!response.ok) {
      throw new Error(`Não foi possível carregar as mensagens: ${response.status} ${response.statusText}`);
    }
    let scriptContent = await response.text();
    if (scriptContent.trim().startsWith('<!DOCTYPE') || scriptContent.trim().startsWith('<html')) {
      throw new Error('Não foi encontrado um arquivo de mensagens válido.');
    }
    scriptContent = scriptContent.replace(/export\s+default\s+/g, 'return ');
    const func = new Function(scriptContent);
    return func();
  }
}
export var OperationMap;
(function (OperationMap) {
  OperationMap["CLONE"] = "clone";
  OperationMap["INSERT"] = "insert";
  OperationMap["UPDATE"] = "update";
  OperationMap["CLEAN"] = "clean";
  OperationMap["UPDATE_MULTIPLES"] = "updateMultiples";
})(OperationMap || (OperationMap = {}));
