/**
 * Componente responsável pela criação, edição e gerenciamento de filtros personalizados.
 *
 * Permite alternar entre os modos assistente e avançado, salvar, cancelar e manipular filtros.
 *
 * @component
 * @example
 * <snk-personalized-filter
 *    entityUri="sua/entidade"
 *    filterId="idFiltro"
 *    configName="nomeConfig"
 *    resourceID="resourceId"
 *    isDefaultFilter={false}
 *    messagesBuilder={messagesBuilderInstance}
 *    onEzSave={handler}
 *    onEzCancel={handler}
 * />
 */
import { h, Host, Fragment } from '@stencil/core';
import { ApplicationContext, StringUtils } from '@sankhyalabs/core';
import { PersonalizedFilterUtils } from './subcomponents/snk-filter-param-config/utils/PersonalizedFilterUtils';
import { ConfigStorage } from "../../lib/configs/ConfigStorage";
import { ApplicationUtils } from "@sankhyalabs/ezui/dist/collection/utils";
import { ObjectUtils, ElementIDUtils } from "@sankhyalabs/core";
import { FilterGroupCondition } from './interfaces/IExpressionItem';
import store from '../../lib/store';
import PersonalizedFilterFetcher from "../../lib/http/data-fetcher/fetchers/personalized-filter-fetcher";
import { DefaultFilter } from './interfaces';
export class SnkPersonalizedFilter {
  constructor() {
    this._personalizedFilterFetcher = new PersonalizedFilterFetcher();
    this._filterMetadataStorage = new Map();
    this._dataSourceFetcher = {
      fetchData: async (entity) => {
        let entityURI = entity === null || entity === void 0 ? void 0 : entity.uri;
        if (StringUtils.isEmpty(entityURI)) {
          entityURI = this.entityUri;
        }
        if (!this._filterMetadataStorage.has(entityURI)) {
          const filterMetadata = await this._personalizedFilterFetcher.loadFields(entityURI);
          this._filterMetadataStorage.set(entityURI, filterMetadata);
        }
        return this._filterMetadataStorage.get(entityURI);
      }
    };
    this._filterAssistentMode = true;
    this._filterAssistent = undefined;
    this.messagesBuilder = undefined;
    this.entityUri = undefined;
    this.filterId = undefined;
    this.configName = undefined;
    this.resourceID = undefined;
    this.isDefaultFilter = false;
  }
  /**
   * Cria um novo filtro personalizado caso não exista nenhum.
   * @method
   * @returns {Promise<void>}
   */
  async createPersonalizedFilter() {
    const newPersonalizedFilter = {
      name: "",
      active: true,
      expression: "",
      parameters: [],
      assistent: {
        id: StringUtils.generateUUID(),
        items: [
          {
            id: StringUtils.generateUUID(),
            entityName: "",
            fieldName: "",
            description: "",
            fieldLabel: this.getMessage("snkPersonalizedFilter.info.labelDefaultValue"),
            type: undefined,
            expression: undefined,
            operand: undefined,
            paramVariable: false,
            value: undefined,
            systemConfig: null,
            userConfig: null
          }
        ],
        childrenGroups: [],
        operand: FilterGroupCondition.AND
      }
    };
    if (this.isDefaultFilter) {
      this.buildDataDefaultFilter(newPersonalizedFilter);
    }
    this._originalFilterAssistent = ObjectUtils.copy(newPersonalizedFilter);
    this._filterAssistent = ObjectUtils.copy(newPersonalizedFilter);
  }
  /**
   * Carrega o filtro personalizado com base no identificador informado.
   * @watch filterId
   * @param newValue Novo valor do filtroId.
   * @param oldValue Valor anterior do filtroId.
   */
  loadFilter(newValue, oldValue) {
    if (newValue == null || oldValue == newValue || this.resourceID == undefined) {
      return;
    }
    if (newValue === DefaultFilter.id) {
      ConfigStorage.loadDefaultFilter(newValue, this.resourceID, this.configName)
        .then((resp) => {
        const personalizedFilter = this.applyDefaultValues(resp);
        this._filterAssistent = personalizedFilter;
        this._originalFilterAssistent = ObjectUtils.copy(personalizedFilter);
        this._filterAssistentMode = this._filterAssistent.hasOwnProperty("assistent") && this._filterAssistent.assistent != undefined;
      });
      return;
    }
    ConfigStorage.loadPersonalizedFilter(newValue, this.resourceID, this.configName)
      .then((resp) => {
      const personalizedFilter = this.applyDefaultValues(resp);
      this._filterAssistent = personalizedFilter;
      this._originalFilterAssistent = ObjectUtils.copy(personalizedFilter);
      this._filterAssistentMode = this._filterAssistent.hasOwnProperty("assistent") && this._filterAssistent.assistent != undefined;
    });
  }
  componentWillLoad() {
    var _a;
    if (store.get(`filterFieldsDataSource.${this.entityUri}`) == undefined) {
      store.set(`filterFieldsDataSource.${this.entityUri}`, this._dataSourceFetcher);
    }
    if (!this.messagesBuilder) {
      this._application = ApplicationContext.getContextValue("__SNK__APPLICATION__");
      this.messagesBuilder = (_a = this._application) === null || _a === void 0 ? void 0 : _a.messagesBuilder;
    }
    this.loadFilter(this.filterId, undefined);
  }
  componentDidRender() {
    var _a;
    (_a = this._viewStackRef) === null || _a === void 0 ? void 0 : _a.show(this._filterAssistentMode ? 0 : 1);
    if (this._elButtonMode) {
      this._elButtonMode.setAttribute(ElementIDUtils.DATA_ELEMENT_ID_ATTRIBUTE_NAME, ElementIDUtils.getInternalIDInfo(`${this._filterAssistentMode ? "advancedMode_ezButton" : "assistentMode_ezButton"}`));
    }
  }
  buildDataDefaultFilter(data) {
    data.name = DefaultFilter.name;
    data.id = DefaultFilter.id;
  }
  getMessage(key, params) {
    return this._application.messagesBuilder.getMessage(key, params);
  }
  async saveFilter() {
    let response;
    if (this.isDefaultFilter) {
      response = await ConfigStorage.saveDefaultFilter(this._filterAssistent, this.resourceID, this.configName);
    }
    else {
      response = await ConfigStorage.savePersonalizedFilter(this._filterAssistent, this.resourceID, this.configName);
    }
    this._elButtonSave.enabled = false;
    const messageToken = !!this._filterAssistent.id ? 'confirmEdit' : 'confirmSave';
    ApplicationUtils.info(this.getMessage(`snkPersonalizedFilter.${messageToken}.title`), { iconName: "check" });
    const updatedFilterAssistent = Object.assign(Object.assign({}, response), this._filterAssistent);
    updatedFilterAssistent.parameters = PersonalizedFilterUtils.buildVariableParameters(this._filterAssistent.assistent);
    this._originalFilterAssistent = ObjectUtils.copy(updatedFilterAssistent);
    this._filterAssistent = ObjectUtils.copy(updatedFilterAssistent);
    this.ezAfterSave.emit();
  }
  removeFilter() {
    ConfigStorage.removePersonalizedFilter(this._filterAssistent, this.resourceID, this.configName);
  }
  hasChangesToSave() {
    return JSON.stringify(this._filterAssistent) === JSON.stringify(this._originalFilterAssistent);
  }
  async handleSave() {
    if (this._filterAssistentMode) {
      const isValid = PersonalizedFilterUtils.validateFields(this._filterAssistent.assistent);
      if (!isValid || !this._filterAssistent.name)
        return this._application.error(this.getMessage("snkPersonalizedFilter.error.title"), this.getMessage("snkPersonalizedFilter.error.description"));
      this.saveAssistentMode();
    }
    else {
      if (!this._filterAssistent.expression || !this._filterAssistent.name)
        return this._application.error(this.getMessage("snkPersonalizedFilter.error.title"), this.getMessage("snkPersonalizedFilter.error.description"));
      const isValidExpressionForAdvancedMode = await this.validateExpressionBeforeSaving();
      if (!isValidExpressionForAdvancedMode)
        return;
      this.saveAdvancedMode();
    }
  }
  saveAssistentMode() {
    const { assistent, expression } = this._filterAssistent;
    const expressionQuery = !!assistent ? PersonalizedFilterUtils.buildGroupExpression(assistent) : expression;
    this._filterAssistent.expression = expressionQuery;
    this.ezSave.emit(expressionQuery);
    this.saveFilter();
  }
  saveAdvancedMode() {
    if (this._originalFilterAssistent.expression !== this._filterAssistent.expression && this._filterAssistent.assistent) {
      ApplicationUtils.confirm(this.getMessage("snkPersonalizedFilter.confirmSaveModeAdvanced.title"), this.getMessage("snkPersonalizedFilter.confirmSaveModeAdvanced.description"))
        .then((confirm) => {
        if (!confirm)
          return;
        this.saveAndTransformToAdvancedMode();
      });
    }
    else if (!this._filterAssistent.assistent) {
      this.saveAndTransformToAdvancedMode();
    }
    else {
      this.saveAssistentMode();
    }
  }
  saveAndTransformToAdvancedMode() {
    this._filterAssistent.assistent = undefined;
    this.ezSave.emit(this._filterAssistent.expression);
    this.saveFilter();
  }
  async validateExpressionBeforeSaving() {
    const { valid, message = "" } = await this._personalizedFilterFetcher.validatePersonalizedFilter(this.entityUri, this._filterAssistent.expression);
    valid || this._application.error(this.getMessage("snkPersonalizedFilter.errorValidation.title"), message.replace(/.*Exception: /, ''));
    return valid;
  }
  handleCancel() {
    if (this.hasChangesToSave()) {
      return this.ezCancel.emit();
    }
    ApplicationUtils.confirm(this.getMessage("snkPersonalizedFilter.confirmCancel.title"), this.getMessage("snkPersonalizedFilter.confirmCancel.description"))
      .then((canCancel) => {
      var _a;
      if (!canCancel)
        return;
      this._filterAssistent = ObjectUtils.copy((_a = this._originalFilterAssistent) !== null && _a !== void 0 ? _a : {});
      this.ezCancel.emit();
      this._elButtonSave.enabled = false;
    });
  }
  handleTitleChange(name) {
    this._filterAssistent = Object.assign(Object.assign({}, this._filterAssistent), { name });
    this._elButtonSave.enabled = !this.hasChangesToSave();
  }
  applyDefaultValues(personalizedFilter) {
    this.addLabelToItems(personalizedFilter);
    this.addFilterGroupCondition(personalizedFilter);
    return personalizedFilter;
  }
  addFilterGroupCondition(personalizedFilter) {
    if (personalizedFilter.assistent && !personalizedFilter.assistent.operand) {
      personalizedFilter.assistent.operand = FilterGroupCondition.AND;
    }
  }
  ;
  addLabelToItems(personalizedFilter) {
    //Workaround: Alguns filtros foram salvos sem o fieldLabel. Para evitar transtornos
    //tentamos usar o fieldLabel que pode estar informado no parametro.
    if (personalizedFilter.assistent && personalizedFilter.assistent.items && personalizedFilter.assistent.items.length > 0) {
      personalizedFilter.assistent.items.forEach(item => {
        if (item.fieldLabel == undefined) {
          const param = (personalizedFilter.parameters || []).find(param => param.fieldName === item.fieldName);
          if (param) {
            item.fieldLabel = param.label;
          }
        }
      });
    }
  }
  handleExpressionChangeAdvancedMode(expression) {
    this._filterAssistent = Object.assign(Object.assign({}, this._filterAssistent), { expression });
    this._elButtonSave.enabled = !this.hasChangesToSave();
  }
  handleChangeFilterAssistentMode(filterAssistent) {
    this._elButtonSave.enabled = !this.hasChangesToSave();
    this._filterAssistent = Object.assign({}, filterAssistent);
  }
  selectField(fieldName) {
    if (!('name' in fieldName))
      return;
    const fieldExpression = this.buildExpression(fieldName.entityName, fieldName.name, fieldName.entityPath);
    const textAreaElement = this._elAdvancedMode.querySelector('ez-text-area');
    textAreaElement.appendTextToSelection(fieldExpression);
  }
  buildExpression(entityName, fieldName, entityPath) {
    if (entityPath.length > 0) {
      entityPath.shift();
    }
    return entityPath.length > 0 ? `${entityPath.join("->")}->${fieldName}` : `${entityName}.${fieldName}`;
  }
  onAddField(target) {
    const textAreaElement = this._elAdvancedMode.querySelector('ez-text-area');
    const options = { horizontalGap: 0, verticalGap: 12, fromRight: true };
    textAreaElement.setFocus();
    target.setBlur();
    if (this._elFilterFieldSearch)
      this._elFilterFieldSearch.show(target, options);
  }
  renderButtonAddField() {
    if (this._filterAssistentMode)
      return;
    return (h(Fragment, null, h("ez-button", { class: "snk-personalized-filter__button-mode", label: this.getMessage("snkPersonalizedFilter.info.addField"), enabled: true, onClick: (evt) => this.onAddField(evt.target) }, h("ez-icon", { class: "ez-padding-right--small", slot: "leftIcon", iconName: "plus" })), h("snk-filter-field-search", { class: "ez-padding-left--medium", ref: ref => this._elFilterFieldSearch = ref, onEzSelectFilterItem: (evt) => this.selectField(evt.detail), fieldsDataSource: this._dataSourceFetcher })));
  }
  buildContainerPersonalizedFilter() {
    return (h("ez-view-stack", { ref: (ref) => this._viewStackRef = ref }, h("stack-item", null, this._filterAssistentMode &&
      h("snk-filter-assistent-mode", { filterAssistent: this._filterAssistent, messagesBuilder: this.messagesBuilder, filterId: this.filterId, entityUri: this.entityUri, application: this._application, onEzChangeFilter: (ev) => this.handleChangeFilterAssistentMode(ev.detail), isDefaultFilter: this.isDefaultFilter })), h("stack-item", null, h("snk-filter-advanced-mode", { ref: (ref) => this._elAdvancedMode = ref, filterAssistent: this._filterAssistent, application: this._application, onEzExpressionChange: (ev) => this.handleExpressionChangeAdvancedMode(ev.detail) }))));
  }
  handleModeChange() {
    var _a, _b;
    if (this._filterAssistentMode) {
      ApplicationUtils.confirm(this.getMessage("snkPersonalizedFilter.confirmChangeModeAssistent.title"), this.getMessage("snkPersonalizedFilter.confirmChangeModeAssistent.description"))
        .then((canCancel) => {
        if (!canCancel)
          return;
        this._filterAssistentMode = !this._filterAssistentMode;
        if (!this.hasChangesToSave()) {
          const expression = PersonalizedFilterUtils.buildGroupExpression(this._filterAssistent.assistent);
          this._filterAssistent.expression = expression;
          this._elButtonSave.enabled = !this.hasChangesToSave();
        }
      });
    }
    else {
      if (((_a = this._filterAssistent) === null || _a === void 0 ? void 0 : _a.expression) === ((_b = this._originalFilterAssistent) === null || _b === void 0 ? void 0 : _b.expression)) {
        this._filterAssistentMode = !this._filterAssistentMode;
      }
      else {
        const expressionBefore = this._filterAssistent.expression;
        const expression = PersonalizedFilterUtils.buildGroupExpression(this._filterAssistent.assistent);
        if (expressionBefore !== expression) {
          ApplicationUtils.confirm(this.getMessage("snkPersonalizedFilter.confirmChangeModeAdvanced.title"), this.getMessage("snkPersonalizedFilter.confirmChangeModeAdvanced.description"))
            .then((canCancel) => {
            if (!canCancel)
              return;
            this._filterAssistent = Object.assign(Object.assign({}, this._filterAssistent), { expression });
            this._filterAssistentMode = !this._filterAssistentMode;
          });
        }
        else {
          this._filterAssistentMode = !this._filterAssistentMode;
        }
      }
    }
  }
  buildTitle() {
    if (this.isDefaultFilter && !this.filterId) {
      return this.getMessage("snkPersonalizedFilter.info.titleCreateDefault");
    }
    if (this.isDefaultFilter && this.filterId) {
      return this.getMessage("snkPersonalizedFilter.info.titleEditDefault");
    }
    if (this.filterId) {
      return this.getMessage("snkPersonalizedFilter.info.titleEdit");
    }
    return this.getMessage("snkPersonalizedFilter.info.titleAdd");
  }
  render() {
    var _a, _b, _c, _d;
    if (!((_a = this._filterAssistent) === null || _a === void 0 ? void 0 : _a.assistent) && this._filterAssistentMode) {
      return;
    }
    return (h(Host, null, h("div", { class: "snk-personalized-filter" }, h("div", null, h("snk-simple-bar", { label: this.buildTitle(), onExit: () => this.handleCancel() }, h("div", { class: "snk-personalized-filter__header-actions", slot: "rightSlot" }, h("ez-button", { size: "small", label: this.getMessage("snkPersonalizedFilter.info.labelCancel"), onClick: () => this.handleCancel() }), h("ez-button", { size: "small", ref: (el) => this._elButtonSave = el, enabled: false, class: "ez-button--primary", label: this.getMessage("snkPersonalizedFilter.info.labelSave"), onClick: this.handleSave.bind(this) })))), h("div", { class: "ez-box ez-margin-bottom--medium ez-box__main" }, h("div", { class: "ez-box__container" }, h("div", { class: "ez-flex ez-flex--column ez-size-width--full" }, h("div", { class: "ez-flex" }, h("ez-tooltip", { message: this.getMessage("snkPersonalizedFilter.info.textInputDisabled"), active: this.isDefaultFilter }, h("ez-text-input", { class: "ez-padding-right--medium", label: this.getMessage("snkPersonalizedFilter.info.labelNameFilter"), value: (_b = this._filterAssistent) === null || _b === void 0 ? void 0 : _b.name, onEzChange: (evt) => this.handleTitleChange(evt.detail), enabled: !this.isDefaultFilter })), this.renderButtonAddField(), h("ez-button", { ref: (el) => this._elButtonMode = el, class: "snk-personalized-filter__button-mode", label: this._filterAssistentMode ? this.getMessage("snkPersonalizedFilter.info.activeModeAdvanced") : this.getMessage("snkPersonalizedFilter.info.activeModeAssistent"), onClick: () => this.handleModeChange(), "data-tooltip": !(this._filterAssistentMode || ((_c = this._filterAssistent) === null || _c === void 0 ? void 0 : _c.assistent)) ? this.getMessage("snkPersonalizedFilter.info.tooltipDisabledAssistentMode") : undefined, "data-flow": "bottom", enabled: (!this._filterAssistent.name || Boolean(this._filterAssistentMode || ((_d = this._filterAssistent) === null || _d === void 0 ? void 0 : _d.assistent))) })), this.buildContainerPersonalizedFilter()))))));
  }
  static get is() { return "snk-personalized-filter"; }
  static get encapsulation() { return "scoped"; }
  static get originalStyleUrls() {
    return {
      "$": ["snk-personalized-filter.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["snk-personalized-filter.css"]
    };
  }
  static get properties() {
    return {
      "messagesBuilder": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "SnkMessageBuilder",
          "resolved": "SnkMessageBuilder",
          "references": {
            "SnkMessageBuilder": {
              "location": "import",
              "path": "../../lib/message/SnkMessageBuilder"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }],
          "text": "Respons\u00E1vel por flexibilizar e padronizar o uso de mensagens nos blocos de constru\u00E7\u00E3o."
        }
      },
      "entityUri": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }],
          "text": "URI da entidade utilizada para buscar os campos dispon\u00EDveis para filtro."
        },
        "attribute": "entity-uri",
        "reflect": false
      },
      "filterId": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }],
          "text": "Identificador do filtro a ser carregado."
        },
        "attribute": "filter-id",
        "reflect": false
      },
      "configName": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }],
          "text": "Nome da configura\u00E7\u00E3o, utilizado para distinguir m\u00FAltiplas inst\u00E2ncias do componente."
        },
        "attribute": "config-name",
        "reflect": false
      },
      "resourceID": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }],
          "text": "Identificador do recurso utilizado para salvar e recuperar filtros."
        },
        "attribute": "resource-i-d",
        "reflect": false
      },
      "isDefaultFilter": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [{
              "name": "property",
              "text": undefined
            }, {
              "name": "default",
              "text": "false"
            }],
          "text": "Indica se o filtro \u00E9 o filtro padr\u00E3o do sistema."
        },
        "attribute": "is-default-filter",
        "reflect": false,
        "defaultValue": "false"
      }
    };
  }
  static get states() {
    return {
      "_filterAssistentMode": {},
      "_filterAssistent": {}
    };
  }
  static get events() {
    return [{
        "method": "ezCancel",
        "name": "ezCancel",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [{
              "name": "event",
              "text": undefined
            }],
          "text": "Evento emitido ao cancelar a personaliza\u00E7\u00E3o do filtro."
        },
        "complexType": {
          "original": "void",
          "resolved": "void",
          "references": {}
        }
      }, {
        "method": "ezSave",
        "name": "ezSave",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [{
              "name": "event",
              "text": undefined
            }],
          "text": "Evento emitido ao salvar as altera\u00E7\u00F5es do filtro personalizado."
        },
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        }
      }, {
        "method": "ezAfterSave",
        "name": "ezAfterSave",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [{
              "name": "event",
              "text": undefined
            }],
          "text": "Evento emitido ap\u00F3s salvar as altera\u00E7\u00F5es do filtro personalizado."
        },
        "complexType": {
          "original": "void",
          "resolved": "void",
          "references": {}
        }
      }];
  }
  static get methods() {
    return {
      "createPersonalizedFilter": {
        "complexType": {
          "signature": "() => Promise<void>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global"
            },
            "IPersonalizedFilter": {
              "location": "import",
              "path": "./interfaces/IPersonalizedFilter"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "Cria um novo filtro personalizado caso n\u00E3o exista nenhum.",
          "tags": [{
              "name": "method",
              "text": undefined
            }, {
              "name": "returns",
              "text": undefined
            }]
        }
      }
    };
  }
  static get watchers() {
    return [{
        "propName": "filterId",
        "methodName": "loadFilter"
      }];
  }
}
