'use strict';

const index = require('./index-17105557.js');
const core = require('@sankhyalabs/core');
const utils = require('@sankhyalabs/ezui/dist/collection/utils');
const DataFetcher = require('./DataFetcher-21f8c2dc.js');
const dataunitFetcher = require('./dataunit-fetcher-6c85a04d.js');
const DataType = require('@sankhyalabs/core/dist/dataunit/metadata/DataType');
const GetSelectedRecordsIDsInfo = require('./GetSelectedRecordsIDsInfo-bd50caf1.js');

const NO_TAB_NAME = "__NO_TAB_NAME__";
const MAIN_TAB_NAME = "__main";
async function showConfirmMultipleUpdatePopup({ title, labelBtnConfirm, labelBtnCancel, message, changingFields, }) {
  return new Promise((resolve) => {
    const popup = builPopup(title, resolve);
    const contentContainer = buildContentContainer();
    contentContainer.appendChild(buildMessage(message));
    contentContainer.appendChild(buildChangesContainer(changingFields));
    const actionsContainer = buildActionsContainer();
    actionsContainer.appendChild(buildCancelBtn(popup, labelBtnCancel, resolve));
    actionsContainer.appendChild(buildConfirmBtn(popup, labelBtnConfirm, resolve));
    contentContainer.appendChild(actionsContainer);
    popup.appendChild(contentContainer);
    document.body.appendChild(popup);
  });
}
function groupChanges(changingFields) {
  const changesMap = new Map();
  changingFields.forEach(change => {
    var _a;
    const key = (_a = change.tabName) !== null && _a !== void 0 ? _a : NO_TAB_NAME;
    if (!changesMap.has(key))
      changesMap.set(key, []);
    changesMap.get(key).push(change);
  });
  return changesMap;
}
function getTabName(tabName) {
  const application = core.ApplicationContext.getContextValue("__SNK__APPLICATION__");
  const labelPrincipal = application.messagesBuilder.getMessage("snkDataUnit.main");
  switch (tabName) {
    case NO_TAB_NAME:
      return "";
    case MAIN_TAB_NAME:
      return labelPrincipal;
    default:
      return tabName;
  }
}
function buildChangesDiv(tabName, changes) {
  const changeLabel = document.createElement('span');
  changeLabel.innerText = getTabName(tabName);
  changeLabel.style.display = 'block';
  changeLabel.style.fontWeight = 'var(--text-weight--large, 500)';
  changeLabel.style.fontSize = 'var(--text--medium, 14px)';
  changeLabel.style.marginBottom = 'var(--space--small, 6px)';
  const changeDiv = document.createElement('div');
  changeDiv.style.padding = 'var(--space--medium, 12px) 0';
  changeDiv.style.borderTop = '1px solid var(--color--disable-secondary, #f2f5f8)';
  changeDiv.appendChild(changeLabel);
  changes.forEach(change => {
    const changeLine = document.createElement('span');
    changeLine.innerHTML = `${change.label}: <span style="color: var(--text--primary, #626e82)">${change.value}</span>`;
    changeLine.style.display = 'block';
    changeLine.style.marginBottom = 'var(--space--extra-small, 3px)';
    changeDiv.appendChild(changeLine);
  });
  return changeDiv;
}
function buildChangesContainer(changingFields) {
  const changesContainer = document.createElement('div');
  changesContainer.style.flexDirection = 'column';
  changesContainer.style.display = 'flex';
  changesContainer.style.overflow = 'auto';
  changesContainer.style.maxHeight = '300px';
  const changesMap = groupChanges(changingFields);
  changesMap.forEach((changes, key) => {
    changesContainer.appendChild(buildChangesDiv(key, changes));
  });
  return changesContainer;
}
function buildMessage(messageContent) {
  const message = document.createElement('p');
  message.textContent = messageContent;
  message.style.fontSize = 'var(--text--medium, 14px)';
  return message;
}
function buildContentContainer() {
  const contentContainer = document.createElement('div');
  contentContainer.style.display = 'flex';
  contentContainer.style.flexDirection = 'column';
  contentContainer.style.fontFamily = 'var(--font-pattern, Roboto)';
  contentContainer.style.fontSize = 'var(--text--medium, 14px)';
  return contentContainer;
}
function buildActionsContainer() {
  const actionsContainer = document.createElement('div');
  actionsContainer.style.display = 'flex';
  actionsContainer.style.flexDirection = 'row';
  actionsContainer.style.justifyContent = 'flex-end';
  actionsContainer.style.gap = '5px';
  return actionsContainer;
}
function builPopup(title, resolve) {
  const popup = document.createElement('ez-popup');
  popup.opened = true;
  popup.size = 'small';
  popup.ezTitle = title;
  popup.heightMode = 'auto';
  popup.addEventListener('ezClosePopup', () => {
    document.body.removeChild(popup);
    resolve(false);
  }, { once: true });
  popup.addEventListener('ezPopupAction', () => {
    document.body.removeChild(popup);
    resolve(false);
  }, { once: true });
  return popup;
}
function buildConfirmBtn(popup, confirmBtnLabel, resolve) {
  const confirmBtn = document.createElement('ez-button');
  confirmBtn.label = confirmBtnLabel;
  confirmBtn.size = 'medium';
  confirmBtn.classList.add('ez-button--primary');
  confirmBtn.onclick = () => {
    document.body.removeChild(popup);
    resolve(true);
  };
  return confirmBtn;
}
function buildCancelBtn(popup, cancelBtnLabel, resolve) {
  const cancelBtn = document.createElement('ez-button');
  cancelBtn.label = cancelBtnLabel;
  cancelBtn.size = 'medium';
  cancelBtn.onclick = () => {
    document.body.removeChild(popup);
    resolve(false);
  };
  return cancelBtn;
}

const SnkDataUnit = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.dataStateChange = index.createEvent(this, "dataStateChange", 3);
    this.dataUnitReady = index.createEvent(this, "dataUnitReady", 3);
    this.messagesBuilderUpdated = index.createEvent(this, "messagesBuilderUpdated", 3);
    this.dataUnitFieldsHidded = index.createEvent(this, "dataUnitFieldsHidded", 7);
    this.insertionMode = index.createEvent(this, "insertionMode", 3);
    this.cancelEdition = index.createEvent(this, "cancelEdition", 3);
    this._onDataUnitResolve = [];
    this._openedAlert = false;
    this._fieldsWithRmp = [];
    this._fieldsWithRmPrecision = [];
    this._metadataByRow = new Map();
    this._rowMetadataCache = new Map();
    this._formFieldsConfig = [];
    this._internalDataStateChange = false;
    this.REGEX_DATAUNIT_NAME = /dd:\/\/(.+?)\//;
    this._dataUnitObserver = async (action) => {
      const duState = await this.buildDataState(action.type);
      this.dataState = duState;
      this.messagesBuilder.currentOperation = this.getMessageOperation();
      switch (action.type) {
        case core.Action.DATA_SAVED:
          await this.handleDataSaved(action);
          break;
        case core.Action.RECORDS_ADDED:
        case core.Action.RECORDS_COPIED:
          this.insertionMode.emit();
          break;
        case core.Action.EDITION_CANCELED:
          this.cancelEdition.emit();
          break;
        case core.Action.RECORDS_REMOVED:
          this.handleRecordsRemoved(action);
          break;
        case core.Action.METADATA_LOADED:
          this.fillFieldsWithRmp(this.dataUnit.metadata);
          this.fillFieldsWithRmPrecision(this.dataUnit.metadata);
          break;
      }
    };
    this.fieldsToLink = [];
    this.dataState = undefined;
    this.messagesBuilder = undefined;
    this.dataUnitName = undefined;
    this.entityName = undefined;
    this.pageSize = 150;
    this.dataUnit = undefined;
    this.beforeSave = undefined;
    this.afterSave = undefined;
    this.useCancelConfirm = true;
    this.ignoreSaveMessage = undefined;
    this.configName = undefined;
    this.resourceID = undefined;
    this.domainMessagesBuilder = undefined;
  }
  observePageSize() {
    if (this.dataUnit) {
      this.dataUnit.pageSize = this.pageSize;
    }
  }
  observeDataUnitName(newValue, oldValue) {
    if (oldValue != newValue) {
      if (this.dataUnit) {
        this._application.updateDataunitCache(oldValue, this.dataUnitName, this.dataUnit);
      }
      else {
        this.loadDataUnit();
      }
    }
  }
  observeEntityName(newValue, oldValue) {
    if (oldValue != newValue) {
      this.dataUnit = undefined;
      this.entityName = newValue;
      this.loadDataUnit();
    }
  }
  observeDataState(newValue, oldValue) {
    if (core.ObjectUtils.objectToString(oldValue) != core.ObjectUtils.objectToString(newValue)) {
      this.dataStateChange.emit(newValue);
    }
  }
  observeDataUnit() {
    this.handlerLinkFields();
    this.dataUnitReady.emit(this.dataUnit);
  }
  observeMessagesBuilder(newValue) {
    if (newValue) {
      this.messagesBuilderUpdated.emit(newValue);
    }
  }
  onMasterFormConfigChange({ detail }) {
    var _a;
    this._formFieldsConfig = (_a = detail === null || detail === void 0 ? void 0 : detail.fields) !== null && _a !== void 0 ? _a : [];
  }
  /**
   * Obtém o dataUnit.
   * @returns {Promise<DataUnit>} Uma promessa que resolve com a instância do DataUnit.
   * @async
   */
  async getDataUnit() {
    return new Promise((resolve) => {
      if (this.dataUnit) {
        resolve(this.dataUnit);
      }
      else {
        this._onDataUnitResolve.push(resolve);
      }
    });
  }
  /**
   * Método que retorna a lista de IDs dos registros selecionados.
   * @returns {Promise<Array<IRecordID>>} Retorna uma promessa que resolve com a lista de IDs dos registros selecionados.
   * @async
   */
  async getSelectedRecordsIDsInfo() {
    return GetSelectedRecordsIDsInfo.getSelectedRecordsIDsInfo(this.dataUnit);
  }
  /**
   * Retorna os campos que possuem a propriedade "rmp" (Row Metadata Provider).
   * @returns {Promise<string[]>} Uma promessa que resolve com um array de nomes de campos.
   * @async
   */
  async getFieldsWithRmp() {
    return this._fieldsWithRmp;
  }
  /**
   * Retorna os campos que possuem a propriedade "rm_precision" (Row Metadata Precision).
   * @returns {Promise<string[]>} Uma promessa que resolve com um array de nomes de campos.
   * @async
   */
  async getFieldsWithRmPrecision() {
    return this._fieldsWithRmPrecision;
  }
  /**
   * Busca os metadados da linha selecionada.
   * @param {Record | string} [record] - O registro ou ID do registro para o qual buscar os metadados. Se omitido, usa o registro selecionado.
   * @returns {Promise<RowMetadata>} Uma promessa que resolve com os metadados da linha.
   * @async
   */
  async getRowMetadata(record) {
    return this.doGetRowMetadata(record);
  }
  async doGetRowMetadata(record) {
    const selectedRecord = this.dataUnit.getSelectedRecord();
    if (!record && !selectedRecord) {
      return;
    }
    const currentRecord = record || selectedRecord;
    const recordId = typeof currentRecord === 'string' ? currentRecord : currentRecord.__record__id__;
    let rowMetadata = this._metadataByRow.get(recordId);
    /*
      Nao fazemos cache de metadataByRow pra registros novos, pois a chave do mesmo
      muda ao ser salvo, por isso essa tratativa é necessária para que o dataState fique com metadados
      corretos nao confiando apenas no _metadataByRow
    */
    if (this.dataUnit.isNewRecord(recordId) && !rowMetadata) {
      rowMetadata = await this.handleLoadRowMetadata(selectedRecord);
    }
    if (!rowMetadata) {
      return;
    }
    rowMetadata.getProp = this.buildGetPropRowMetadata(rowMetadata);
    return Object.assign({}, rowMetadata);
  }
  buildGetPropRowMetadata(rowMetadata) {
    return (propPath, fieldName) => {
      if (propPath === "rm_precision") {
        propPath = this.resolvePrecisionFromMetadata(fieldName);
      }
      return core.ObjectUtils.getProp(rowMetadata, propPath);
    };
  }
  resolvePrecisionFromMetadata(fieldName) {
    var _a, _b;
    if (!fieldName) {
      utils.ApplicationUtils.error(this.getMessage("snkDataUnit.fieldNameRequired"));
      return;
    }
    const rmPrecision = (_b = (_a = this.dataUnit.getField(fieldName)) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.rm_precision;
    if (!rmPrecision) {
      return '';
    }
    let rmPrecisionPath = rmPrecision.split('.').filter((_, index) => index !== 1).join('.');
    return rmPrecisionPath;
  }
  getCleanOnCopyFields() {
    var _a;
    return (_a = this.dataUnit.metadata) === null || _a === void 0 ? void 0 : _a.fields.filter(field => { var _a; return (_a = field.properties) === null || _a === void 0 ? void 0 : _a.cleanOnCopy; }).map(field => field.name);
  }
  fillFieldsWithRmp(payload) {
    payload.fields.forEach((field) => {
      var _a;
      if (((_a = field.properties) === null || _a === void 0 ? void 0 : _a.rmp) && !this._fieldsWithRmp.includes(field.name)) {
        this._fieldsWithRmp.push(field.name);
      }
    });
  }
  fillFieldsWithRmPrecision(payload) {
    payload.fields.forEach((field) => {
      var _a;
      if (((_a = field.properties) === null || _a === void 0 ? void 0 : _a.rm_precision) && !this._fieldsWithRmPrecision.includes(field.name)) {
        this._fieldsWithRmPrecision.push(field.name);
      }
    });
  }
  getCacheName(fieldName, metadataName, fieldValue) {
    const cacheName = [fieldName, metadataName, fieldValue].join("_");
    return cacheName;
  }
  updateDataStateRmp(newValue) {
    const newRowMetadata = Object.assign({}, newValue);
    this.dataState.rowMetadata = newRowMetadata;
  }
  saveCacheRmd(record) {
    const rmd = record.__record__metadata__;
    const keysRmd = Object.keys(rmd);
    keysRmd.shift();
    keysRmd.forEach((fieldName) => {
      const fieldValue = dataunitFetcher.getRecordValue(record, fieldName);
      const cacheName = this.getCacheName(fieldName, rmd.provider, fieldValue);
      this._rowMetadataCache.set(cacheName, Object.assign({}, rmd));
    });
  }
  getMetadataByRow(payload) {
    var _a;
    if (!((_a = payload.records) === null || _a === void 0 ? void 0 : _a.length)) {
      return payload;
    }
    if (!this._fieldsWithRmp.length) {
      const records = payload.records.map((record) => {
        delete record.__record__metadata__;
        return record;
      });
      return Object.assign(Object.assign({}, payload), { records });
    }
    const records = payload.records.map((record) => {
      if (!record.__record__metadata__) {
        return record;
      }
      this.saveCacheRmd(record);
      const rowMetadata = Object.assign({}, record.__record__metadata__);
      rowMetadata.getProp = this.buildGetPropRowMetadata(rowMetadata);
      this._metadataByRow.set(record.__record__id__, rowMetadata);
      delete record.__record__metadata__;
      return record;
    });
    return Object.assign(Object.assign({}, payload), { records });
  }
  interceptRecordsAdded(action) {
    if (!this.isAllowed("INSERT")) {
      utils.ApplicationUtils.info(this.getMessage("snkDataUnit.forbiddenInsert"));
      return;
    }
    return new core.DataUnitAction(core.Action.RECORDS_ADDED, this.handleLinksWithParent(action.payload));
  }
  interceptRecordsCopied(action) {
    if (!this.isAllowed("CLONE")) {
      utils.ApplicationUtils.info(this.getMessage("snkDataUnit.forbiddenClone"));
      return;
    }
    return new core.DataUnitAction(core.Action.RECORDS_COPIED, this.handleRecordsCopied(action.payload));
  }
  async interceptDataChange(action) {
    var _a;
    const recordId = (_a = this.dataUnit.getSelectedRecord()) === null || _a === void 0 ? void 0 : _a.__record__id__;
    if (this.isAllowed("UPDATE") || this.dataUnit.isNewRecord(recordId)) {
      return action;
    }
    if (this._internalDataStateChange) {
      this._internalDataStateChange = false;
      return;
    }
    if (this._openedAlert) {
      this._internalDataStateChange = true;
      await this.dataUnit.cancelEdition();
      return;
    }
    this._openedAlert = true;
    this._internalDataStateChange = true;
    await this.dataUnit.cancelEdition();
    await utils.ApplicationUtils.alert(this.getMessage("snkDataUnit.forbidden"), this.getMessage("snkDataUnit.forbiddenUpdate"));
    this._openedAlert = false;
  }
  async interceptSavingData(action) {
    if (this.dataUnit.isMultipleEdition) {
      const confirm = await this.confirmMultipleSavingData();
      if (!confirm)
        return undefined;
    }
    if (!this.beforeSave)
      return action;
    const continueAction = this.beforeSave(this.dataUnit);
    if (continueAction instanceof Promise) {
      const result = await continueAction;
      return result ? action : undefined;
    }
    return continueAction ? action : undefined;
  }
  async confirmMultipleSavingData() {
    const selectedRecords = this.dataUnit.getSelectionInfo().records;
    const title = this.getMessage('snkDataUnit.multipleUpdateConfirmationTitle');
    const message = this.getMessage('snkDataUnit.multipleUpdateConfirmationMessage', { size: selectedRecords.length });
    const labelBtnCancel = this.getMessage('snkDataUnit.confirm.cancel');
    const labelBtnConfirm = this.getMessage('snkDataUnit.confirm.updateMultipleConfirm');
    return await showConfirmMultipleUpdatePopup({
      title,
      message,
      labelBtnConfirm,
      labelBtnCancel,
      changingFields: this.getChangingFields(),
    });
  }
  getChangingFields() {
    const changes = this.dataUnit.buildChangesToSave();
    if (!(changes === null || changes === void 0 ? void 0 : changes.length))
      return [];
    const change = changes[0];
    const changingFields = Object.keys(change.updatingFields).map(key => this.buildChangingField(key, change[key]));
    return changingFields;
  }
  buildChangingField(key, value) {
    const fieldLabel = this.dataUnit.getField(key).label;
    const formattedValue = this.dataUnit.getFormattedValue(key, value);
    return {
      label: fieldLabel,
      value: formattedValue,
      tabName: this.getFieldTabName(key),
    };
  }
  getFieldTabName(fieldName) {
    var _a;
    const tab = (_a = this._formFieldsConfig.find(f => f.name === fieldName)) === null || _a === void 0 ? void 0 : _a.tab;
    if (!tab)
      return undefined;
    if (typeof tab === 'string')
      return tab;
    return tab.label;
  }
  interceptDataSaved(action) {
    if (this.afterSave) {
      this.afterSave(this.dataUnit);
      return;
    }
    return action;
  }
  async interceptEditionCanceled(action) {
    var _a, _b;
    if (!this.useCancelConfirm || !this.dataState.hasDirtyRecords || ((_a = action.payload) === null || _a === void 0 ? void 0 : _a.fromParent) || ((_b = action.payload) === null || _b === void 0 ? void 0 : _b.silent)) {
      return action;
    }
    const cancelConfirmation = this.getMessage("snkDataUnit.cancelConfirmation");
    if (cancelConfirmation == undefined) {
      this.showSuccessMessage(this.getMessage("snkDataUnit.cancelInfo"));
      return action;
    }
    const cancelConfirmationTitle = this.getMessage("snkDataUnit.cancelConfirmationTitle");
    const confirm = await utils.ApplicationUtils.confirm(cancelConfirmationTitle, cancelConfirmation);
    if (confirm) {
      let editionCanceledMessage;
      if (this.dataUnit.isMultipleEdition) {
        const selectedRecords = this.dataUnit.getSelectionInfo().records;
        editionCanceledMessage = this.buildMultipleUpdateMessage(selectedRecords, true);
      }
      else {
        editionCanceledMessage = this.getMessage("snkDataUnit.cancelInfo");
      }
      this.showSuccessMessage(editionCanceledMessage);
    }
    return confirm ? action : undefined;
  }
  async interceptRemovingRecords(action) {
    var _a, _b, _c;
    if (!this.isAllowed("REMOVE")) {
      utils.ApplicationUtils.info(this.getMessage("snkDataUnit.forbiddenRemove"));
      return;
    }
    let multipleSelection = false;
    let removeConfirmation = !((_a = action.payload) === null || _a === void 0 ? void 0 : _a.silent) && this.getMessage("snkDataUnit.removeConfirmation");
    const selection = (_b = this.dataUnit) === null || _b === void 0 ? void 0 : _b.getSelectionInfo();
    if (!((_c = action.payload) === null || _c === void 0 ? void 0 : _c.silent) && (selection === null || selection === void 0 ? void 0 : selection.length) > 1) {
      removeConfirmation = this.getMessage("snkDataUnit.removeAllConfirmation", { size: selection.length });
      multipleSelection = true;
    }
    if (!removeConfirmation) {
      return action;
    }
    const options = {
      canClose: false,
      labelCancel: this.getMessage(`snkDataUnit.confirm.${multipleSelection ? "no" : "cancel"}`),
      labelConfirm: this.getMessage(`snkDataUnit.confirm.${multipleSelection ? "yes" : "delete"}`),
      btnConfirmDanger: false
    };
    const removeConfirmationTitle = this.getMessage("snkDataUnit.removeConfirmationTitle");
    const confirm = await utils.ApplicationUtils.confirm(removeConfirmationTitle, removeConfirmation, null, utils.DialogType.WARN, options);
    return confirm ? action : undefined;
  }
  interceptDataLoaded(action) {
    const newPayload = this.getMetadataByRow(action.payload);
    action = new core.DataUnitAction(core.Action.DATA_LOADED, newPayload);
    return action;
  }
  interceptMetadataLoaded(action) {
    this.fillFieldsWithRmp(action.payload);
    this.fillFieldsWithRmPrecision(action.payload);
    return new core.DataUnitAction(core.Action.METADATA_LOADED, this.handleDULinksOnMetadataLoaded(action.payload));
  }
  async interceptAction(action) {
    switch (action.type) {
      case core.Action.RECORDS_ADDED:
        return this.interceptRecordsAdded(action);
      case core.Action.RECORDS_COPIED:
        return this.interceptRecordsCopied(action);
      case core.Action.DATA_CHANGED:
        await this.handleLoadRowMetadata(action.payload);
        return await this.interceptDataChange(action);
      case core.Action.CHANGING_DATA:
        return await this.interceptDataChange(action);
      case core.Action.SAVING_DATA:
        return await this.interceptSavingData(action);
      case core.Action.DATA_SAVED:
        return this.interceptDataSaved(action);
      case core.Action.EDITION_CANCELED:
        return await this.interceptEditionCanceled(action);
      case core.Action.REMOVING_RECORDS:
        return await this.interceptRemovingRecords(action);
      case core.Action.DATA_LOADED:
        return this.interceptDataLoaded(action);
      case core.Action.METADATA_LOADED:
        return this.interceptMetadataLoaded(action);
      default:
        return action;
    }
  }
  async handleLoadRowMetadata(record) {
    if (!record)
      return;
    const keysPayload = Object.keys(record);
    const rmpField = keysPayload.find((field) => this._fieldsWithRmp.includes(field));
    if (rmpField) {
      const metadataName = this.dataUnit.getField(rmpField).properties.rmp;
      const fieldValue = dataunitFetcher.getRecordValue(record, rmpField);
      return await this.updateRowMetadata({
        fieldName: rmpField,
        fieldValue,
        metadataName,
        updatedFields: record,
      });
    }
  }
  async updateRowMetadata({ fieldName, fieldValue, metadataName, updatedFields }) {
    const cacheName = this.getCacheName(fieldName, metadataName, fieldValue);
    const cacheValue = this._rowMetadataCache.get(cacheName);
    if (cacheValue) {
      this.updateDataStateRmp(cacheValue);
      return cacheValue;
    }
    else {
      const datasetStrategy = new dataunitFetcher.DatasetStrategy();
      const response = await datasetStrategy.loadRowMetadata(this, fieldName, metadataName, updatedFields);
      this.updateDataStateRmp(response._rmd);
      this._rowMetadataCache.set(cacheName, Object.assign({}, response._rmd));
      return Object.assign({}, response._rmd);
    }
  }
  handleDULinksOnMetadataLoaded(payload) {
    const metadata = Object.assign({}, payload);
    this.processLinks(metadata);
    return metadata;
  }
  handleRecordsCopied(initialRecords) {
    let records = [...initialRecords];
    records = this.handleCleanOnCopy(records);
    return this.handleLinksWithParent(records);
  }
  handleLinksWithParent(records) {
    var _a, _b;
    const parentDataUnit = (_a = this._parentDataUnit) !== null && _a !== void 0 ? _a : (_b = this.dataUnit) === null || _b === void 0 ? void 0 : _b.getParentDataUnit();
    if (!parentDataUnit)
      return records;
    const parentSelectedRecord = parentDataUnit.getSelectedRecord();
    const selfInfo = parentDataUnit === null || parentDataUnit === void 0 ? void 0 : parentDataUnit.getChildInfo(this.getCleanDataUnitName());
    const { links } = selfInfo;
    if (!links || links.length === 0)
      return records;
    return records.map(record => {
      return this.buildRecordWithLinkedFields(record, links, parentSelectedRecord);
    });
  }
  buildRecordWithLinkedFields(record, links, parentSelectedRecord) {
    const newRecord = Object.assign({}, record);
    links.forEach(link => {
      const convertedParentSelectedRecord = DataType.convertType(this.dataUnit.getField(link.target).dataType, parentSelectedRecord[link.source]);
      newRecord[link.target] = convertedParentSelectedRecord;
    });
    return newRecord;
  }
  handleCleanOnCopy(records) {
    const cleanFields = this.getCleanOnCopyFields();
    if (cleanFields.length > 0) {
      records = records.map(record => this.buildCopyWithCleanedFields(record, cleanFields));
    }
    return records;
  }
  buildCopyWithCleanedFields(record, cleanFields) {
    const newRecord = Object.assign({}, record);
    cleanFields.forEach(fieldName => delete newRecord[fieldName]);
    return newRecord;
  }
  showSuccessMessage(message) {
    utils.ApplicationUtils.info(message, { iconName: "check" });
  }
  isAllowed(flag) {
    return this._permissions ? this._permissions.isSup || this._permissions[flag] : false;
  }
  async buildDataState(actionType) {
    var _a;
    const selectionInfo = this.dataUnit.getSelectionInfo();
    const isStartingInsertionMode = (this.dataUnit.hasDirtyRecords() || this.dataUnit.hasWaitingChanges()) && (selectionInfo === null || selectionInfo === void 0 ? void 0 : selectionInfo.isEmpty());
    const selectedRecord = this.dataUnit.getSelectedRecord();
    let rowMetadata = (_a = this.dataState) === null || _a === void 0 ? void 0 : _a.rowMetadata;
    const allowedOverwrite = [core.Action.SELECTION_CHANGED, core.Action.EDITION_CANCELED, core.Action.NEXT_SELECTED, core.Action.PREVIOUS_SELECTED];
    if (selectedRecord && (!rowMetadata || allowedOverwrite.includes(actionType))) {
      rowMetadata = await this.doGetRowMetadata(selectedRecord);
    }
    else if (rowMetadata) {
      rowMetadata.getProp = this.buildGetPropRowMetadata(rowMetadata);
    }
    return new DataStateImpl({
      insertionMode: this.dataUnit.hasNewRecord(),
      isStartingInsertionMode,
      hasNext: this.dataUnit.hasNext(),
      hasPrevious: this.dataUnit.hasPrevious(),
      copyMode: this.dataUnit.hasCopiedRecord(),
      isDirty: this.dataUnit.isDirty(),
      hasDirtyRecords: this.dataUnit.hasDirtyRecords(),
      selectedRecords: undefined,
      selectionInfo,
      selectedRecord,
      recordsIsEmpty: this.dataUnit.records.length === 0,
      metadataByRow: this._metadataByRow,
      rowMetadata
    });
  }
  async handleDataSaved(action) {
    var _a, _b, _c;
    const changes = (_a = action === null || action === void 0 ? void 0 : action.payload) === null || _a === void 0 ? void 0 : _a.changes;
    const affectedRecords = (_b = action === null || action === void 0 ? void 0 : action.payload) === null || _b === void 0 ? void 0 : _b.records;
    const newRowMetadata = await this.handleLoadRowMetadata((_c = changes === null || changes === void 0 ? void 0 : changes[0]) === null || _c === void 0 ? void 0 : _c.record);
    if (newRowMetadata) {
      newRowMetadata.getProp = this.buildGetPropRowMetadata(newRowMetadata);
    }
    const recordId = affectedRecords[0].__record__id__;
    this._metadataByRow.set(recordId, newRowMetadata);
    this.dataState = await this.buildDataState();
    let saveOperation = changes[0]._operation.toLowerCase();
    if (saveOperation == 'copy') {
      saveOperation = DataFetcher.OperationMap.CLONE;
    }
    if (this.canIgnoreOperationMessage(saveOperation))
      return;
    let msg = this.buildOperationMessage(saveOperation, affectedRecords);
    if (msg != undefined) {
      this.showSuccessMessage(msg);
    }
  }
  canIgnoreOperationMessage(saveOperation) {
    return this.ignoreSaveMessage && !this.isCloneOrInsertOperation(saveOperation);
  }
  isCloneOrInsertOperation(saveOperation) {
    return [DataFetcher.OperationMap.CLONE, DataFetcher.OperationMap.INSERT].includes(saveOperation);
  }
  buildOperationMessage(saveOperation, records) {
    if (this.isMultiplesUpdate(saveOperation, records)) {
      return this.buildMultipleUpdateMessage(records);
    }
    return this.getMessage('snkDataUnit.saveInfo', records[0], saveOperation);
  }
  buildMultipleUpdateMessage(records, isCancel) {
    /**
     * FIXME: No futuro, precisamos pensar em um mecanismo para deixar as mensagens de feedback mais dinâmicas.
     * Podemo ocorrer cenários onde temos mais de um registro selecionado e também cenários onde a chave primária
     * de um registro se trata de uma chave composta.
     */
    const key = `snkDataUnit.${isCancel ? 'cancelInfo' : 'saveInfo'}`;
    return this.getMessage(key, { records: records }, DataFetcher.OperationMap.UPDATE_MULTIPLES);
  }
  isMultiplesUpdate(saveOperation, records) {
    return saveOperation === DataFetcher.OperationMap.UPDATE && records.length > 1;
  }
  handleRecordsRemoved(action) {
    var _a, _b;
    let removeFinishMsg = this.buildRemoveFinishMessage(action);
    if (removeFinishMsg != undefined) {
      this.showSuccessMessage(removeFinishMsg);
    }
    const recordsCount = (_b = (_a = this.dataUnit.records) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
    const paginationInfo = this.dataUnit.getPaginationInfo();
    if (paginationInfo) {
      const page = recordsCount > 0 || paginationInfo.hasMore ? paginationInfo.currentPage : 0;
      this.dataUnit.gotoPage(page);
    }
  }
  buildRemoveFinishMessage(action) {
    const records = action.payload.records;
    if (!records || !records.length)
      return undefined;
    if ((records === null || records === void 0 ? void 0 : records.length) > 1)
      return this.getMessage('snkDataUnit.removeAllInfo', { size: records.length });
    return this.getMessage('snkDataUnit.removeInfo', records);
  }
  /**
   * 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-data-unit.msg.ts"
   */
  getMessage(key, params = undefined, customOperation) {
    if (!params) {
      params = this.getMessageParams();
    }
    if (customOperation) {
      this.messagesBuilder.currentOperation = customOperation;
    }
    return this.messagesBuilder.getMessage(key, params);
  }
  getMessageParams() {
    //FIXME: Devido ao recurso de multiseleção do dataunit, precisaremos criar um mecanismo para
    //oferecer todos os registros selecionados para a mensagem, pois mensagens podem ficar incorretas.
    return this.dataState.selectedRecord;
  }
  getMessageOperation() {
    if (this.dataState.copyMode) {
      return DataFetcher.OperationMap.CLONE;
    }
    if (this.dataState.insertionMode || this.dataState.isStartingInsertionMode) {
      return DataFetcher.OperationMap.INSERT;
    }
    if (this.dataState.isDirty) {
      return DataFetcher.OperationMap.UPDATE;
    }
    return DataFetcher.OperationMap.CLEAN;
  }
  async getDataUnitParentOrChild() {
    var _a;
    const cacheName = this.dataUnitName ? this.dataUnitName : this.entityName;
    if (this._parentSnkDataUnit) {
      this._parentDataUnit = await ((_a = this._parentSnkDataUnit) === null || _a === void 0 ? void 0 : _a.getDataUnit());
      return await this._application.getDataUnit(this.entityName, cacheName, this._parentDataUnit, this.configName, this.resourceID);
    }
    else {
      return await this._application.getDataUnit(this.entityName, cacheName, null, this.configName, this.resourceID);
    }
  }
  updateMetadataWithRMP() {
    this.fillFieldsWithRmp(this.dataUnit.metadata);
    this.fillFieldsWithRmPrecision(this.dataUnit.metadata);
    const dataUnitUpdatedMetadata = this.handleDULinksOnMetadataLoaded(this.dataUnit.metadata);
    this.dataUnit.metadata = dataUnitUpdatedMetadata;
  }
  async loadDataUnit() {
    var _a, _b;
    if (this.dataUnit == null && this._application && this.entityName) {
      this.dataUnit = await this.getDataUnitParentOrChild();
    }
    if (this.dataUnit) {
      this.dataUnit.pageSize = this.pageSize;
      this.dataUnit.unsubscribe(this._dataUnitObserver);
      this.dataUnit.subscribe(this._dataUnitObserver);
      if ((_a = this.dataUnit) === null || _a === void 0 ? void 0 : _a.metadata) {
        this.updateMetadataWithRMP();
      }
      this.dataUnit.addInterceptor(this);
      if ((_b = this.dataUnit.records) === null || _b === void 0 ? void 0 : _b.length) {
        const { records } = this.getMetadataByRow(this.dataUnit);
        this.dataUnit.setRecordsKeepingSelection(records);
      }
      this.dataState = await this.buildDataState();
      let resolver;
      while (resolver = this._onDataUnitResolve.pop()) {
        resolver(this.dataUnit);
      }
    }
  }
  getParentSnkDataUnit() {
    let currentElement = this.element;
    while (currentElement.parentNode) {
      if (currentElement.parentNode.nodeName === 'SNK-DATA-UNIT') {
        return currentElement.parentNode;
      }
      currentElement = currentElement.parentNode;
    }
    return;
  }
  handlerLinkFields() {
    var _a, _b, _c, _d;
    const parentDU = (_a = this._parentDataUnit) !== null && _a !== void 0 ? _a : (_b = this.dataUnit) === null || _b === void 0 ? void 0 : _b.getParentDataUnit();
    if (!parentDU)
      return;
    const childName = (_c = this.entityName) !== null && _c !== void 0 ? _c : this.getCleanDataUnitName();
    const child = parentDU.getChildInfo(childName);
    if (!child)
      return;
    const links = (_d = child === null || child === void 0 ? void 0 : child.links) === null || _d === void 0 ? void 0 : _d.map(link => link.target);
    this.handleDUWithLinks(links);
  }
  handleDUWithLinks(fieldsToLink) {
    this.fieldsToLink = fieldsToLink;
    const metadata = Object.assign({}, this.dataUnit.metadata);
    this.processLinks(metadata);
    this.dataUnit.metadata = metadata;
    this.dataUnitFieldsHidded.emit();
  }
  processLinks(metadata) {
    var _a;
    (_a = metadata === null || metadata === void 0 ? void 0 : metadata.fields) === null || _a === void 0 ? void 0 : _a.forEach(field => {
      var _a;
      if ((_a = this.fieldsToLink) === null || _a === void 0 ? void 0 : _a.includes(field.name)) {
        field.visible = false;
      }
    });
  }
  getCleanDataUnitName() {
    var _a;
    const uri = this.dataUnit.name;
    if (core.StringUtils.isEmpty(uri))
      return uri;
    const matcher = this.REGEX_DATAUNIT_NAME.exec(uri);
    return (_a = matcher === null || matcher === void 0 ? void 0 : matcher[1]) !== null && _a !== void 0 ? _a : uri;
  }
  static getNearestInstance(element) {
    let parent = element.parentElement;
    while (parent) {
      if (parent.tagName.toUpperCase() === "SNK-DATA-UNIT") {
        return parent;
      }
      parent = parent.parentElement;
    }
  }
  instanceMessagesBuilder() {
    var _a;
    if (this.messagesBuilder) {
      return;
    }
    this.messagesBuilder = new DataFetcher.SnkMessageBuilder((_a = this.domainMessagesBuilder) !== null && _a !== void 0 ? _a : this.entityName);
  }
  //---------------------------------------------
  // Lifecycle web component
  //---------------------------------------------
  componentWillLoad() {
    this._application = core.ApplicationContext.getContextValue("__SNK__APPLICATION__");
    this._application.getAllAccess(this.resourceID).then(access => this._permissions = access);
    this._parentSnkDataUnit = this.getParentSnkDataUnit();
    this.instanceMessagesBuilder();
  }
  disconnectedCallback() {
    if (this.dataUnit) {
      this.dataUnit.releaseCallbacks();
    }
  }
  async componentDidLoad() {
    await this.loadDataUnit();
    this.handlerLinkFields();
  }
  render() {
    return (index.h(index.Host, null));
  }
  get element() { return index.getElement(this); }
  static get watchers() { return {
    "pageSize": ["observePageSize"],
    "dataUnitName": ["observeDataUnitName"],
    "entityName": ["observeEntityName"],
    "dataState": ["observeDataState"],
    "dataUnit": ["observeDataUnit"],
    "messagesBuilder": ["observeMessagesBuilder"]
  }; }
};
class DataStateImpl {
  constructor(datastate) {
    this.copyMode = datastate.copyMode;
    this.insertionMode = datastate.insertionMode;
    this.isStartingInsertionMode = datastate.isStartingInsertionMode;
    this.isDirty = datastate.isDirty;
    this.hasDirtyRecords = datastate.hasDirtyRecords;
    this.hasNext = datastate.hasNext;
    this.hasPrevious = datastate.hasPrevious;
    this.selectionInfo = datastate.selectionInfo;
    this.selectedRecord = datastate.selectedRecord;
    this.recordsIsEmpty = datastate.recordsIsEmpty;
    this.metadataByRow = datastate.metadataByRow;
    this.rowMetadata = datastate.rowMetadata;
  }
}

exports.SnkDataUnit = SnkDataUnit;
