import { ObjectUtils, StringUtils } from '@sankhyalabs/core';
import { C as ConfigStorage } from './ConfigStorage.js';
import { F as FormConfigFetcher } from './form-config-fetcher.js';
import { T as TAB_NAMES } from './constants.js';

class SnkFormConfigManager {
  constructor(configName, resourceID, onConfigChange, dataUnit) {
    this._resourceID = resourceID;
    this._configName = configName;
    this._onConfigChange = onConfigChange;
    this._dataUnit = dataUnit;
  }
  addFormLegacyConfig(legacyConfigName) {
    if (this._configName) {
      ConfigStorage.addFormLegacyConfig(this._configName, legacyConfigName);
    }
  }
  async loadConfig() {
    return new Promise(resolve => {
      ConfigStorage.loadFormConfig(this._configName, this._resourceID)
        .then((config) => {
        config = this.buildFormMetadataUITabs(config);
        this.setConfig(config);
        resolve(config);
      })
        .catch((error) => {
        console.warn(error);
      });
    });
  }
  getEmptyConfig() {
    return this.buildFormMetadataUITabs({ fields: [], emptyConfig: true }, true);
  }
  saveConfig(config) {
    const configToSave = ObjectUtils.copy(config);
    return new Promise(accept => {
      ConfigStorage.saveFormConfig(config, this._configName, this._resourceID)
        .then((response) => {
        this.setConfig(Object.assign(Object.assign({}, configToSave), response));
        accept(Object.assign(Object.assign({}, configToSave), response));
      });
    });
  }
  saveCardState(cardId, cardConfig, propertyChanged) {
    return new Promise(resolve => {
      var _a;
      const cardsState = ((_a = this._config) === null || _a === void 0 ? void 0 : _a.cardsState) || new Map;
      const currentConfig = cardsState.get(cardId);
      cardsState.set(cardId, propertyChanged === "fixed" ?
        this.updateFixSequence(Object.assign(Object.assign({}, currentConfig), { fixed: cardConfig.fixed }), cardsState)
        : Object.assign(Object.assign({}, currentConfig), { [propertyChanged]: cardConfig[propertyChanged] }));
      ConfigStorage.saveCardState(cardsState, this._configName, this._resourceID)
        .then(savedCardConfig => {
        this._config = Object.assign(Object.assign({}, this._config), { cardsState });
        resolve(savedCardConfig);
      });
    });
  }
  updateFixSequence(updatingCardConfig, cardsState) {
    let maxSequence = -1;
    Array.from(cardsState.values()).forEach(cardConfig => {
      if (!cardConfig.fixed) {
        delete updatingCardConfig.fixSequence;
      }
      if (cardConfig.fixSequence != undefined) {
        maxSequence = Math.max(maxSequence, cardConfig.fixSequence);
      }
    });
    if (updatingCardConfig.fixed) {
      updatingCardConfig.fixSequence = maxSequence + 1;
    }
    else {
      delete updatingCardConfig.fixSequence;
    }
    return updatingCardConfig;
  }
  hasConfig(config) {
    var _a;
    const currentConfig = config !== null && config !== void 0 ? config : this._config;
    if (currentConfig && ((_a = currentConfig.fields) === null || _a === void 0 ? void 0 : _a.length)) {
      return true;
    }
    return false;
  }
  getFieldsList(descriptionFilter, forceEmptyConfig = false) {
    var _a, _b;
    const fields = (_a = this._config) === null || _a === void 0 ? void 0 : _a.fields;
    const hasConfig = this.hasConfig();
    if (hasConfig && !forceEmptyConfig) {
      return fields.map(({ label, name, readOnly, visible, required, tab, group }) => {
        var _a;
        if (label == undefined) {
          const currentField = (_a = this._dataUnit) === null || _a === void 0 ? void 0 : _a.getField(name);
          if (!currentField)
            return;
          return Object.assign(Object.assign({}, currentField), { name: name !== null && name !== void 0 ? name : currentField.name, readOnly: readOnly !== null && readOnly !== void 0 ? readOnly : currentField.readOnly, visible: visible !== null && visible !== void 0 ? visible : currentField.visible, required: required !== null && required !== void 0 ? required : currentField.required, tab: tab, group: group });
        }
        return { name, label, readOnly, visible, required, tab, group };
      })
        .filter(field => this.isFieldVisible(field, descriptionFilter));
    }
    if (!this._dataUnit || !((_b = this._dataUnit.metadata) === null || _b === void 0 ? void 0 : _b.fields)) {
      return [];
    }
    const filteredFields = this._dataUnit.metadata.fields
      .filter(field => this.isFieldVisible(field, descriptionFilter))
      .map(({ label, name, readOnly, visible, required, properties }) => ({ label, name, readOnly, visible, required, tab: properties === null || properties === void 0 ? void 0 : properties.UITabName }));
    return filteredFields;
  }
  isFieldVisible(field, descriptionFilter) {
    if (field === undefined || field.visible === false) {
      return false;
    }
    if (descriptionFilter == undefined) {
      return true;
    }
    const normalizedText = StringUtils.replaceAccentuatedCharsLower((field.label || field.name).toLocaleLowerCase());
    const normalizedFilter = StringUtils.replaceAccentuatedCharsLower(descriptionFilter.toLocaleLowerCase());
    return normalizedText.includes(normalizedFilter);
  }
  getFormConfig(dataUnit, ignoreReadOnlyFormFields, forceEmptyConfig = false) {
    let fields = this.getFieldsList(undefined, forceEmptyConfig);
    if (ignoreReadOnlyFormFields) {
      fields = fields.filter(field => {
        if (dataUnit) {
          const def = dataUnit.getField(field.name);
          if (def && def.readOnly) {
            return false;
          }
        }
        return !field.readOnly;
      });
    }
    return Object.assign(Object.assign({}, this._config), { fields });
  }
  setConfig(config) {
    this.isLoaded = true;
    const { cardsState, summary, defaultVars } = this._config || {};
    this._config = Object.assign({}, config);
    if (cardsState) {
      this._config.cardsState = cardsState;
    }
    if (summary) {
      this._config.summary = summary;
    }
    if (defaultVars) {
      this._config.defaultVars = defaultVars;
    }
    if (this._onConfigChange) {
      this._onConfigChange(Object.assign({}, this._config));
    }
  }
  getConfig(dataUnit, ignoreReadOnlyFormFields) {
    return this.getFormConfig(dataUnit, ignoreReadOnlyFormFields);
  }
  getFormConfigFetcher() {
    if (this._formConfigFetcher == undefined) {
      this._formConfigFetcher = new FormConfigFetcher();
    }
    return this._formConfigFetcher;
  }
  async fetchUserAvailableConfigs() {
    if (this._configName != undefined) {
      //FIXME: Precisamos preparar o backend para retornar as configurações disponíveis para details;
      return Promise.resolve(undefined);
    }
    return this.getFormConfigFetcher().fetchUserAvailableConfigs(this._configName, this._resourceID);
  }
  async fetchLegacyConfig() {
    return this.getFormConfigFetcher().fetchLegacyConfig(this._configName, this._resourceID);
  }
  async fetchDefaultConfig() {
    return this.getFormConfigFetcher().fetchDefaultConfig(this._configName, this._resourceID);
  }
  parseObjectList(object) {
    if (!object) {
      return [];
    }
    return Array.isArray(object) ? object : [object];
  }
  buildFormMetadataUITabs(config, forceEmptyConfig = false) {
    var _a, _b, _c;
    const hasConfig = this.hasConfig(config);
    if (!forceEmptyConfig && (!this._dataUnit || hasConfig)) {
      return config;
    }
    config = this.getFormConfig(this._dataUnit, false, true);
    config.tabs = this.parseObjectList(config.tabs);
    config.emptyConfig = false;
    config.defaultConfiguration = true;
    const fields = (_b = (_a = this._dataUnit.metadata) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [];
    for (const currentField of fields) {
      const field = config.fields.find(field => field.name === currentField.name);
      const uiTabName = (_c = currentField.properties) === null || _c === void 0 ? void 0 : _c.UITabName;
      if (!uiTabName || uiTabName === TAB_NAMES.main) {
        continue;
      }
      const haveTab = config.tabs.some((tab) => tab.label === uiTabName);
      if (!haveTab) {
        config.tabs.push({
          label: uiTabName,
          name: uiTabName,
          order: 0,
          visible: true,
        });
      }
      if (field) {
        field.tab = uiTabName;
      }
    }
    return config;
  }
}

export { SnkFormConfigManager as S };
