'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-17105557.js');
const core = require('@sankhyalabs/core');
const SnkFormConfigManager = require('./SnkFormConfigManager-cf551c69.js');
const ResourceIDUtils = require('./ResourceIDUtils-5ff86aa7.js');
const form = require('@sankhyalabs/ezui/dist/collection/utils/form');
const utils = require('@sankhyalabs/ezui/dist/collection/utils');
const formConfigFetcher = require('./form-config-fetcher-fef79845.js');
const constants = require('./constants-6d82e405.js');
const FormConfigHelper = require('./FormConfigHelper-1e8bb464.js');
require('./ConfigStorage-b829def9.js');
require('./DataFetcher-21f8c2dc.js');
require('./PrintUtils-bcaeb82f.js');
require('@sankhyalabs/core/dist/dataunit/metadata/UnitMetadata');
require('./filter-item-type.enum-a7ffdaa6.js');

const snkFormCss = ".sc-snk-form-h{--snk-form__header--min-height:94px;display:block}.snk-form__form--hidden.sc-snk-form{display:none}";

const SnkForm = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.exit = index.createEvent(this, "exit", 7);
    this.actionClick = index.createEvent(this, "actionClick", 7);
    this.formItemsReady = index.createEvent(this, "formItemsReady", 7);
    this._customEditors = new Map();
    this._dataUnit = undefined;
    this._dataState = undefined;
    this._showFormConfig = false;
    this._configManager = undefined;
    this.configName = undefined;
    this.recordsValidator = undefined;
    this.messagesBuilder = undefined;
    this.formLegacyConfigName = undefined;
    this.resourceID = undefined;
  }
  /**
   * Exibe a janela de configurações do formulário.
   * @async
   * @returns {Promise<void>}
   */
  async showConfig() {
    this._showFormConfig = true;
  }
  /**
   * Fecha a janela de configurações do formulário.
   * @async
   * @returns {Promise<void>}
   */
  async hideConfig() {
    this._showFormConfig = false;
  }
  /**
   * Registra um editor customizado para campos do formulário.
   * @async
   * @param {string} fieldName - Nome do campo.
   * @param {ICustomEditor} customEditor - Editor customizado.
   * @returns {Promise<void>}
   */
  async addCustomEditor(fieldName, customEditor) {
    if (this._form) {
      this._form.addCustomEditor(fieldName, customEditor);
      return;
    }
    const newCustomEditors = new Map(this._customEditors);
    newCustomEditors.set(fieldName, customEditor);
    this._customEditors = newCustomEditors;
  }
  /**
   * Altera/adiciona uma propriedade nos metadados do campo.
   * @async
   * @param {string} fieldName - Nome do campo.
   * @param {string} propName - Nome da propriedade.
   * @param {any} value - Valor da propriedade.
   * @returns {Promise<void>}
   */
  async setFieldProp(fieldName, propName, value) {
    await this._form.setFieldProp(fieldName, propName, value);
  }
  /**
   * Valida o formulário.
   * @async
   * @returns {Promise<void>}
   * @description
   * Este método executa a validação do formulário, verificando se todos os campos estão
   * preenchidos corretamente de acordo com as regras definidas.
   * Se a validação falhar, uma exceção será lançada com os detalhes dos erros encontrados.
   * Caso contrário, o método será resolvido sem erros.
   */
  async validate() {
    await this._form.validate();
  }
  closeConfig() {
    this.hideConfig();
  }
  dataunitReady() {
    const dataInfo = { dataUnit: this._dataUnit };
    core.ElementIDUtils.addIDInfo(this._element, null, dataInfo);
  }
  setCustomEditors() {
    if (!this._form) {
      return;
    }
    for (const [fieldName, customEditor] of this._customEditors) {
      this._form.addCustomEditor(fieldName, customEditor);
      this._customEditors.delete(fieldName);
    }
  }
  async componentDidRender() {
    this.setCustomEditors();
  }
  async componentWillLoad() {
    let parent = this._element.parentElement;
    while (parent) {
      if (parent.tagName.toUpperCase() === "SNK-DATA-UNIT") {
        this._snkDataUnit = parent;
        this._dataUnit = this._snkDataUnit.dataUnit;
        this._dataState = this._snkDataUnit.dataState;
        if (this._dataUnit) {
          this.dataunitReady();
        }
        else {
          this._snkDataUnit.addEventListener("dataUnitReady", (evt) => {
            this._dataUnit = evt.detail;
          });
        }
        this._snkDataUnit.addEventListener("dataStateChange", this.handleDataStateChange.bind(this));
        break;
      }
      parent = parent.parentElement;
    }
    if (this.resourceID == undefined) {
      this.resourceID = await ResourceIDUtils.ResourceIDUtils.getResourceID();
    }
    this._configManager = new SnkFormConfigManager.SnkFormConfigManager(this.configName, this.resourceID, undefined, this._dataUnit);
    this.addFormLegacyConfig();
    await this._configManager.loadConfig();
  }
  async handleDataStateChange(evt) {
    var _a;
    this._dataState = evt.detail;
    const fieldsWithRmPrecision = await this._snkDataUnit.getFieldsWithRmPrecision();
    for (const field of fieldsWithRmPrecision || []) {
      if (!field) {
        continue;
      }
      const rmPrecision = (_a = this._dataState.rowMetadata) === null || _a === void 0 ? void 0 : _a.getProp('rm_precision', field);
      if (!rmPrecision && rmPrecision !== 0) {
        continue;
      }
      await this.setFieldProp(field, 'precision', rmPrecision);
      await this.setFieldProp(field, 'prettyPrecision', rmPrecision);
    }
  }
  addFormLegacyConfig() {
    if (this.formLegacyConfigName) {
      this._configManager.addFormLegacyConfig(this.formLegacyConfigName);
    }
  }
  render() {
    if (!this._dataUnit || !this._dataState) {
      return undefined;
    }
    return (index.h("section", null, index.h("div", { class: "ez-row" }, index.h("div", { class: "ez-col ez-col--sd-12" }, index.h("ez-form", { ref: (ref) => this._form = ref, key: "ezForm" + this._snkDataUnit.entityName, "data-element-id": "embedded", dataUnit: this._dataUnit, config: this._configManager.getConfig(this._dataUnit), recordsValidator: this.recordsValidator, class: this._showFormConfig ? 'snk-form__form--hidden' : '' }), this._showFormConfig &&
      index.h("snk-form-config", { messagesBuilder: this.messagesBuilder, dataUnit: this._dataUnit, configManager: this._configManager, onConfigClose: () => this.closeConfig() })))));
  }
  get _element() { return index.getElement(this); }
};
SnkForm.style = snkFormCss;

const snkFormConfigCss = ".sc-snk-form-config-h{display:flex;flex-direction:column;height:100vh;width:100vw;font-family:var(--font-pattern, \"Roboto\");background:white;color:#2b3a54;--snk-form-config-container-height:calc(100vh - 95px);outline:none}.sidebarNavigator__container.sc-snk-form-config{height:var(--snk-form-config-container-height);gap:20px;align-items:flex-start}.guide-header.sc-snk-form-config{display:flex;width:100%;padding-bottom:12px;border-bottom:1px solid #dce0e8;height:30px;font-weight:500;font-size:16px}";

const SnkFormConfig = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.configClose = index.createEvent(this, "configClose", 7);
    this.configChange = index.createEvent(this, "configChange", 7);
    this.guidesMap = new Map();
    this.availableFields = [];
    this.guidesList = [];
    this.groupsList = [];
    this.selectedGuide = undefined;
    this._formConfig = {};
    this.configOptions = [];
    this.originalConfigSelected = undefined;
    this.configSelected = undefined;
    this.hasChanges = false;
    this.optionConfigChanged = false;
    this.dataUnit = undefined;
    this.configManager = undefined;
    this.ignoreReadOnlyFormFields = undefined;
    this.messagesBuilder = undefined;
  }
  handleFieldConfigChanged() {
    this.hasChanges = true;
  }
  async handleFormConfigOptionSelected({ detail }) {
    this.configSelected = detail;
    await this.loadConfigByUser();
    this.selectedGuide = undefined;
    this.optionConfigChanged = !core.ObjectUtils.equals(this.configSelected, this.originalConfigSelected);
    if (this.configSelected.origin === formConfigFetcher.UserConfigType.DEFAULT) {
      this.hasChanges = false;
    }
  }
  async handleAddFieldToGuide({ detail: fieldItem }) {
    var _a;
    if (!this.selectedGuide) {
      this.showNoGuideSelectedDialog();
      return;
    }
    if (this.selectedGuide.isCustom || this.selectedGuide.isDetail) {
      this.showCanNotAddFieldToGuideDialog();
      return;
    }
    this.availableFields = [...this.availableFields.filter(f => f.name !== fieldItem.name)];
    await ((_a = this.refFieldsLayout) === null || _a === void 0 ? void 0 : _a.addFieldToLayout(fieldItem));
  }
  async handleSetFieldAsAvailable({ detail }) {
    const hasField = this.availableFields.some(f => f.name === detail.name);
    if (hasField)
      return;
    this.availableFields = [...this.availableFields, detail];
  }
  async handleRemoveFieldFromAvailable({ detail }) {
    this.availableFields = this.availableFields.filter(f => f.name !== detail.name);
  }
  observeSelectedGuide(guide) {
    var _a;
    const guideGroups = (_a = this.guidesMap.get(guide === null || guide === void 0 ? void 0 : guide.name)) !== null && _a !== void 0 ? _a : [];
    this.groupsList = [...guideGroups];
  }
  observeConfigManager() {
    this.loadFormConfig();
  }
  showNoGuideSelectedDialog() {
    const title = this.getMessage('snkFormConfig.noGuideSelected.title');
    const message = this.getMessage('snkFormConfig.noGuideSelected.message');
    utils.ApplicationUtils.alert(title, message);
  }
  showCanNotAddFieldToGuideDialog() {
    const title = this.getMessage('snkFormConfig.canNotAddFieldToGuide.title');
    const message = this.getMessage('snkFormConfig.canNotAddFieldToGuide.message');
    utils.ApplicationUtils.alert(title, message);
  }
  /**
   * Conforme mecanismo de mensagens, é possível customizar as mensagens dos blocos de construção
   * através de um pequeno modulo na estrutura da aplicação:
   * - Criar um arquivo no seguinte caminho: /messages/appmessages.msg.js.
   * Para conhecer os detalhes do módulo, vide o arquivo neste projeto "/src/lib/message/resources/snk-form.msg.ts"
   */
  getMessage(key, params) {
    return this.messagesBuilder.getMessage(key, params);
  }
  async initializeUserConfig() {
    if (this.configManager == undefined)
      return;
    try {
      const userConfig = await this.configManager.fetchUserAvailableConfigs();
      this.configOptions = userConfig;
      const isDefault = this._formConfig != undefined ? this._formConfig.defaultConfiguration : true;
      const origin = (isDefault ? formConfigFetcher.UserConfigType.DEFAULT : formConfigFetcher.UserConfigType.USER);
      this.configSelected = userConfig.find((config) => config.origin === origin);
      this.originalConfigSelected = userConfig.find((config) => config.origin === origin);
    }
    catch (error) {
      console.error(this.getMessage('snkFormConfig.errors.failFetchUserConfig'));
      console.error(error);
    }
  }
  async loadConfigByUser() {
    if (!this.configManager || !this.configSelected)
      return;
    if (this.isConfigDefaultSelected()) {
      await this.handleLoadDefaultConfig();
    }
    else {
      this.loadFormConfig();
    }
  }
  async handleLoadDefaultConfig() {
    const defaultConfig = await this.configManager.fetchDefaultConfig();
    if (defaultConfig) {
      this.loadFormConfig(defaultConfig);
      return;
    }
    const emptyConfig = this.configManager.getEmptyConfig();
    if (emptyConfig) {
      this.loadFormConfig(emptyConfig);
    }
  }
  isConfigDefaultSelected() {
    return this.configSelected.origin === formConfigFetcher.UserConfigType.DEFAULT;
  }
  loadFormConfig(config) {
    this._formConfig = config ? config : this.getConfig();
    this.loadGuides();
    this.initializeAvailableFields();
  }
  initializeAvailableFields() {
    var _a;
    if (((_a = this._formConfig) === null || _a === void 0 ? void 0 : _a.fields) == undefined)
      return;
    const fieldsFormConfig = [...this._formConfig.fields];
    const fieldsMetadata = this.dataUnit.metadata.fields;
    this.availableFields = fieldsMetadata.filter(({ name: fieldName, visible: fieldVisible, properties }) => {
      const hasCfg = fieldsFormConfig.some(({ name: fieldFormName }) => fieldFormName === fieldName);
      /**
       * Quando a visibilidade de um campo é alterada pelo dataunit, mas o desenvolvedor deseja que o mesmo continue
       * sendo apresentado no configurador, precisamos fazer essa tratativa, verificando se o campo não tem configuração
       */
      if (!hasCfg && properties.visibleOnConfig === true && !fieldVisible)
        return properties.visibleOnConfig;
      return fieldVisible === true && hasCfg === false;
    });
  }
  getInitialOrder(guidesList) {
    var _a, _b;
    if (Array.isArray((_a = this._formConfig) === null || _a === void 0 ? void 0 : _a.tabs)) {
      return (_b = this._formConfig.tabs) === null || _b === void 0 ? void 0 : _b.length;
    }
    if (guidesList.length > 0) {
      return Math.max(...guidesList.map(g => g.order));
    }
    return 0;
  }
  loadGuides() {
    var _a;
    this.guidesList = [];
    this.guidesList.push(...FormConfigHelper.buildGuides(this._formConfig, this.getMessage('snkFormConfig.form.mainArea')));
    this.guidesList.push(...FormConfigHelper.buildChildrenGuides(this.dataUnit, this.getInitialOrder(this.guidesList), this.guidesList));
    this.guidesMap = FormConfigHelper.buildGuidesMap((_a = this._formConfig) === null || _a === void 0 ? void 0 : _a.fields, this.guidesList, this.dataUnit, this.getMessage('snkFormConfig.form.tabGeneral'));
  }
  getConfig() {
    let config = this.configManager.getConfig(this.dataUnit, false);
    if (config.fields && config.fields.length === 0) {
      config = undefined;
    }
    if (config == undefined) {
      config = form.buildFormConfigFromDataUnit(this.dataUnit);
    }
    return core.ObjectUtils.copy(config);
  }
  handleSelectGuide({ detail: selectedGuide }) {
    this.selectedGuide = selectedGuide;
  }
  handleLayoutChanged({ detail: newGroupList }) {
    this.hasChanges = true;
    this.groupsList = [...newGroupList];
    this.guidesMap.set(this.selectedGuide.name, [...newGroupList]);
  }
  getIsDefaultConfig() {
    var _a;
    const optionSelected = (_a = this.configSelected) === null || _a === void 0 ? void 0 : _a.origin;
    return optionSelected === formConfigFetcher.UserConfigType.DEFAULT
      && this.optionConfigChanged === true
      && this.hasChanges === false;
  }
  getTabsToSave() {
    return this.guidesList.map(tab => {
      return {
        name: tab.name,
        label: tab.name === constants.TAB_NAMES.main ? tab.name : tab.label,
        order: tab.name === constants.TAB_NAMES.main ? 0 : tab.order,
        visible: tab.visible,
      };
    });
  }
  async handleSaveConfig() {
    var _a;
    const savedConfig = await this.configManager.saveConfig(this.buildConfigToSave());
    this.configSelected = (_a = this.configOptions) === null || _a === void 0 ? void 0 : _a.find((config) => {
      return config.origin === (this.hasChanges ? formConfigFetcher.UserConfigType.USER : formConfigFetcher.UserConfigType.DEFAULT);
    });
    this.originalConfigSelected = this.configSelected;
    this.hasChanges = false;
    this.optionConfigChanged = false;
    utils.ApplicationUtils.info(this.getMessage('snkFormConfig.info.successfullyConfigSaved'), { iconName: 'check' });
    this.configChange.emit(savedConfig);
  }
  buildConfigToSave() {
    if (this.getIsDefaultConfig()) {
      const formConfig = this._formConfig;
      formConfig.defaultConfiguration = true;
      return formConfig;
    }
    const formConfig = core.ObjectUtils.copy(this._formConfig);
    formConfig.tabs = this.getTabsToSave();
    formConfig.fields = FormConfigHelper.getFieldsToSave(this.guidesMap);
    formConfig.defaultConfiguration = false;
    return formConfig;
  }
  handleAvailableFieldListChanged({ detail: updatedList }) {
    this.availableFields = [...updatedList];
  }
  handleSetFieldListAsAvailable({ detail: updatedList }) {
    this.availableFields = [...this.availableFields, ...updatedList];
  }
  handleGuideDeleted({ detail: guide }) {
    var _a, _b;
    const guideName = guide.name;
    const guideGroups = (_a = this.guidesMap.get(guideName)) !== null && _a !== void 0 ? _a : [];
    const fieldsToAvailable = [];
    guideGroups.forEach(group => fieldsToAvailable.push(...group.fields));
    this.availableFields = [...this.availableFields, ...fieldsToAvailable];
    this.guidesList = [...this.guidesList.filter(g => g.name !== guideName)];
    this.guidesMap.delete(guideName);
    if (((_b = this.selectedGuide) === null || _b === void 0 ? void 0 : _b.name) === guideName) {
      this.selectedGuide = undefined;
    }
    this.hasChanges = true;
  }
  handleGuideListChanged({ detail: updatedList }) {
    this.hasChanges = true;
    this.guidesList = [...updatedList];
  }
  handleGuideRenamed({ detail: updatedName }) {
    var _a;
    const guideGroups = (_a = this.guidesMap.get(this.selectedGuide.name)) !== null && _a !== void 0 ? _a : [];
    const updatedGroups = FormConfigHelper.updateTabInFieldsFromGroupList(guideGroups, updatedName);
    this.guidesMap.delete(this.selectedGuide.name);
    this.guidesMap.set(updatedName, updatedGroups);
    const updatedGuide = {
      name: updatedName,
      label: updatedName,
      visible: this.selectedGuide.visible,
      order: this.selectedGuide.order,
    };
    this.guidesList = [...this.guidesList.map(guide => (guide.name === this.selectedGuide.name) ? updatedGuide : guide)];
    this.groupsList = [...updatedGroups];
    this.selectedGuide = updatedGuide;
    this.hasChanges = true;
  }
  handleCreateNewGuide() {
    const newGuideName = FormConfigHelper.buildNewGuideName(this.guidesList, this.getMessage.bind(this));
    const newGuide = {
      name: newGuideName,
      label: newGuideName,
      visible: true,
      order: this.guidesList.length + 1,
    };
    const newGuideFixedGroup = {
      name: constants.GROUP_NAMES.noGroup,
      fields: [],
    };
    this.guidesList = [...this.guidesList, newGuide];
    this.guidesMap.set(newGuideName, [newGuideFixedGroup]);
    this.selectedGuide = newGuide;
    this.hasChanges = true;
  }
  getGuideNames() {
    return [
      ...this.guidesList.map(g => g.name.toLowerCase()),
      this.getMessage('snkFormConfig.form.mainArea').toLowerCase(),
    ];
  }
  async componentWillRender() {
    if (this.messagesBuilder == undefined) {
      const application = core.ApplicationContext.getContextValue('__SNK__APPLICATION__');
      this.messagesBuilder = application.messagesBuilder;
    }
  }
  async componentWillLoad() {
    this.loadFormConfig();
    await this.initializeUserConfig();
  }
  render() {
    return (index.h(index.Host, null, index.h("config-header", { configOptions: this.configOptions, selectedConfig: this.configSelected, messagesBuilder: this.messagesBuilder, hasChanges: this.hasChanges, optionConfigChanged: this.optionConfigChanged, onConfigClose: () => this.configClose.emit(), onSaveConfig: async () => await this.handleSaveConfig() }), index.h("div", { class: "ez-padding--medium" }, index.h("div", { class: "ez-flex sidebarNavigator__container" }, index.h("guides-configurator", { messagesBuilder: this.messagesBuilder, guidesList: this.guidesList, selectedGuide: this.selectedGuide, onGuideSelected: this.handleSelectGuide.bind(this), onGuideListChanged: this.handleGuideListChanged.bind(this), onCreateNewGuide: this.handleCreateNewGuide.bind(this), onGuideDeleted: this.handleGuideDeleted.bind(this) }), index.h("fields-layout", { ref: ref => this.refFieldsLayout = ref, selectedGuide: this.selectedGuide, guideNames: this.getGuideNames(), groupsList: this.groupsList, messagesBuilder: this.messagesBuilder, dataUnit: this.dataUnit, onGuideRenamed: this.handleGuideRenamed.bind(this), onLayoutChanged: this.handleLayoutChanged.bind(this), onSetFieldListAsAvailable: this.handleSetFieldListAsAvailable.bind(this) }), index.h("fields-selector", { dataUnit: this.dataUnit, availableFields: this.availableFields, onFieldListChanged: this.handleAvailableFieldListChanged.bind(this), messagesBuilder: this.messagesBuilder })))));
  }
  static get watchers() { return {
    "selectedGuide": ["observeSelectedGuide"],
    "configManager": ["observeConfigManager"]
  }; }
};
SnkFormConfig.style = snkFormConfigCss;

exports.snk_form = SnkForm;
exports.snk_form_config = SnkFormConfig;
