import { ObjectUtils, StringUtils } from '@sankhyalabs/core';
import { ApplicationUtils } from '@sankhyalabs/ezui/dist/collection/utils';
import { forceUpdate, h, Host, } from '@stencil/core';
import Sortable from 'sortablejs';
import { GROUP_NAMES, TAB_NAMES } from '../../../lib/utils/constants';
import { getFieldsStructure, ID_AVAILABLE_FIELDS, SORTABLE_PATH, } from '../FormConfigHelper';
export class FieldLayoutComponent {
  constructor() {
    this.ID_GROUPS = 'container-groups';
    this.ID_FIELDS = 'container-fields';
    this.reservedGuideNames = [TAB_NAMES.main.toLowerCase(), TAB_NAMES.general.toLocaleLowerCase()];
    this.groupsListMemory = [];
    this.groupsRefList = [];
    this.isEditGuideNameActive = false;
    this.selectedGuide = undefined;
    this.groupsList = [];
    this.guideNames = [];
    this.dataUnit = undefined;
    this.messagesBuilder = undefined;
  }
  onMessagesBuilderChange() {
    this.setCustomCSSProperties();
  }
  handleFieldConfigChanged({ detail: updatedField }) {
    const groupToUpdate = this.groupsListMemory.find(g => g.name === updatedField.group);
    if (!groupToUpdate)
      return;
    const updatedFields = groupToUpdate.fields.map(field => {
      return (field.name === updatedField.name) ? updatedField : field;
    });
    const updatedGroupList = this.groupsListMemory.map(group => {
      return (group.name === groupToUpdate.name)
        ? { name: group.name, fields: updatedFields }
        : group;
    });
    this.applyGroupUpdate(updatedGroupList);
  }
  observeSelectedGuide() {
    this.isEditGuideNameActive = false;
    forceUpdate(this);
    this.isEditingGroupName.emit(false);
  }
  observeGroupList(newValue) {
    this.groupsListMemory = [...newValue];
  }
  observeIsEditGuideNameActive(newValue) {
    this.isEditingGuideName.emit(newValue);
  }
  async addFieldToLayout(incomingField) {
    incomingField.group = GROUP_NAMES.noGroup;
    incomingField.tab = this.selectedGuide.name;
    const fixedFieldsGroup = this.getFixedFieldsGroup();
    const newFixedFieldsGroup = {
      name: GROUP_NAMES.noGroup,
      fields: fixedFieldsGroup ? [...fixedFieldsGroup.fields, incomingField] : [incomingField],
    };
    const updatedGroupListMemory = fixedFieldsGroup
      ? [newFixedFieldsGroup, ...this.groupsListMemory.slice(1)]
      : [newFixedFieldsGroup, ...this.groupsListMemory];
    this.applyGroupUpdate(updatedGroupListMemory);
  }
  getFixedFieldsGroup() {
    return this.groupsListMemory.find(g => g.name === GROUP_NAMES.noGroup);
  }
  getMessage(key, params) {
    return this.messagesBuilder.getMessage(key, params);
  }
  handleAddGroup() {
    const newGroup = { name: this.buildNewGroupName(), fields: [] };
    const updatedGroupsList = [...this.groupsListMemory, newGroup];
    this.applyGroupUpdate(updatedGroupsList);
  }
  buildNewGroupName() {
    var _a, _b;
    const newGroupMessage = this.getMessage('snkFormConfig.form.newGroup');
    const qtdWithNewGroupName = (_b = (_a = this.groupsListMemory.filter(g => g.name.includes(newGroupMessage))) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
    return qtdWithNewGroupName === 0 ? newGroupMessage : `${newGroupMessage} (${qtdWithNewGroupName})`;
  }
  makeDynamicFieldsContainersDraggable() {
    const draggableGroups = this.groupsList.filter((g) => g.name !== GROUP_NAMES.noGroup);
    draggableGroups.forEach(group => {
      this.makeFieldContainerDraggable(this.getFieldsContainerId(group.name));
    });
  }
  getFieldsContainerId(groupName) {
    return `${this.ID_FIELDS}-${StringUtils.replaceBlankCharacters(groupName)}`;
  }
  handleSortGroups(evt) {
    var _a;
    const htmlStructure = (_a = evt.to) === null || _a === void 0 ? void 0 : _a.children;
    if (!htmlStructure)
      return;
    const groupsOrder = Array.from(htmlStructure).map(el => el.getAttribute('data-group-name'));
    const updatedOrderGroupsList = [];
    const fixedGroup = this.getFixedFieldsGroup();
    if (fixedGroup) {
      updatedOrderGroupsList.push(fixedGroup);
    }
    groupsOrder.forEach(groupName => {
      const group = this.groupsListMemory.find(g => g.name === groupName);
      if (group) {
        updatedOrderGroupsList.push(group);
      }
    });
    this.applyGroupUpdate(updatedOrderGroupsList);
  }
  handleFieldsChanged(evt) {
    let updatedGroupsList = [...this.groupsListMemory];
    updatedGroupsList = [...this.handleFieldsOnGroupUpdate(updatedGroupsList, evt, SORTABLE_PATH.FROM)];
    updatedGroupsList = [...this.handleFieldsOnGroupUpdate(updatedGroupsList, evt, SORTABLE_PATH.TO)];
    this.applyGroupUpdate(updatedGroupsList);
  }
  applyGroupUpdate(updatedGroupList) {
    var _a;
    (_a = this.groupsRefList) === null || _a === void 0 ? void 0 : _a.forEach((group) => group === null || group === void 0 ? void 0 : group.cancelEdition());
    if (ObjectUtils.equals(updatedGroupList, this.groupsListMemory)) {
      return false;
    }
    this.groupsListMemory = [...updatedGroupList];
    this.layoutChanged.emit(this.groupsListMemory);
    return true;
  }
  handleFieldsOnGroupUpdate(groupList, evt, path) {
    const element = evt[path];
    const isAvailableFields = element.id === ID_AVAILABLE_FIELDS;
    return isAvailableFields ? groupList : this.updateGroupList(groupList, element, path, evt);
  }
  updateGroupList(groupList, element, path, evt) {
    const groupName = element.getAttribute('data-group-name');
    const updatedGroup = {
      name: groupName,
      fields: getFieldsStructure(evt, path, groupName, this.selectedGuide.name),
    };
    return this.replaceGroup(groupList, updatedGroup);
  }
  replaceGroup(groupList, newGroup) {
    return groupList.map(group => group.name === newGroup.name ? newGroup : group);
  }
  makeGroupsDraggable() {
    try {
      const element = this.getContainerElement(this.ID_GROUPS);
      if (!element)
        return;
      new Sortable(element, {
        group: 'groups',
        ghostClass: 'ghost',
        direction: 'horizontal',
        animation: 15,
        onSort: (evt) => this.handleSortGroups(evt),
      });
    }
    catch (e) {
      console.error(this.getMessage('snkFormConfig.errors.failMakeGroupsDraggable'), this.ID_GROUPS);
    }
  }
  makeFieldContainerDraggable(containerId) {
    try {
      const element = this.getContainerElement(containerId);
      if (!element)
        return;
      new Sortable(element, {
        group: 'fields',
        ghostClass: 'ghost',
        direction: 'vertical',
        animation: 15,
        onAdd: (evt) => this.handleFieldsChanged(evt),
        onRemove: (evt) => this.handleFieldsChanged(evt),
        onSort: (evt) => this.handleFieldsChanged(evt),
      });
    }
    catch (e) {
      console.error(this.getMessage('snkFormConfig.errors.failMakeFieldContainerDraggable'), containerId);
    }
  }
  getContainerElement(id) {
    return this.el.querySelector(`[id="${id}"]`);
  }
  handleSetFieldAsAvailable(field) {
    var _a;
    const groupName = (_a = field.group) !== null && _a !== void 0 ? _a : GROUP_NAMES.noGroup;
    const group = this.groupsListMemory.find(group => group.name === groupName);
    const fields = group.fields.filter(f => f.name !== field.name);
    const updatedGroup = { name: groupName, fields };
    const updatedList = [...this.replaceGroup(this.groupsListMemory, updatedGroup)];
    this.applyGroupUpdate(updatedList);
  }
  removeGroup(group) {
    var _a, _b;
    const groupFields = (_b = (_a = this.groupsListMemory.find(f => f.name === group.name)) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [];
    const updatedGroupList = [...this.groupsListMemory.filter(g => g.name !== group.name)];
    if (this.applyGroupUpdate(updatedGroupList)) {
      this.setFieldListAsAvailable.emit(groupFields);
    }
  }
  handleRenameGroup(editDetails) {
    const { value: actualName, newValue: newGroupName } = editDetails.detail;
    const updatedGroupList = this.groupsListMemory.map(group => {
      if (group.name !== actualName)
        return Object.assign({}, group);
      const updatedFields = group.fields.map(f => {
        return Object.assign(Object.assign({}, f), { group: newGroupName });
      });
      return { name: newGroupName, fields: updatedFields };
    });
    this.applyGroupUpdate(updatedGroupList);
  }
  canSaveGroup(newLabel, index) {
    const hasOtherWithThisName = this.groupsList.some(group => {
      var _a;
      return ((_a = group.name) !== null && _a !== void 0 ? _a : '').toLocaleLowerCase() === (newLabel !== null && newLabel !== void 0 ? newLabel : '').toLocaleLowerCase();
    });
    if (!hasOtherWithThisName)
      return true;
    const title = this.getMessage('snkFormConfig.confirm.title');
    const message = this.buildDuplicatedGroupNameContent(newLabel);
    ApplicationUtils.alert(title, message).then(() => { var _a; return (_a = this.groupsRefList[index]) === null || _a === void 0 ? void 0 : _a.applyFocusTextEdit(); });
    return false;
  }
  buildDuplicatedGroupNameContent(newLabel) {
    const tabName = this.selectedGuide.name;
    return `
        ${this.getMessage('snkFormConfig.alert.titleGroupExists')}
        <b>${newLabel}</b>
        ${this.getMessage('snkFormConfig.alert.inTab')}
        <b>${tabName === TAB_NAMES.main ? this.getMessage('snkFormConfig.form.mainArea') : tabName}</b>.
        <br/><br/>
        ${this.getMessage('snkFormConfig.alert.infoValidTitle')}
      `;
  }
  buildDuplicatedTabNameContent(newLabel) {
    return `
        ${this.getMessage('snkFormConfig.alert.titleGuideExists')}
        <b>${newLabel}</b>.
        <br/><br/>
        ${this.getMessage('snkFormConfig.alert.infoValidTitle')}
      `;
  }
  buildReservedTabNameContent(newLabel) {
    return `
        ${this.getMessage('snkFormConfig.alert.titleGuideReservedName')}
        <br/><br/>
        <b>${newLabel}</b>.
        <br/><br/>
        ${this.getMessage('snkFormConfig.alert.infoValidTitle')}
      `;
  }
  renderFields(fields) {
    if (fields.length === 0)
      return;
    return fields.map(field => (h("field-item", { key: field.name, fieldConfig: field, onLayoutConfig: true, dataUnit: this.dataUnit, messagesBuilder: this.messagesBuilder, onSetFieldAsAvailable: (e) => this.handleSetFieldAsAvailable(e.detail) })));
  }
  renderDraggableGroups() {
    const draggableGroups = this.groupsList.filter(g => g.name !== GROUP_NAMES.noGroup);
    return (draggableGroups.map((group, index) => {
      var _a;
      return (h("div", { key: group.name, class: 'group-config', "data-group-name": group.name }, h("ez-collapsible-box", { ref: ref => this.groupsRefList[index] = ref, label: group.name, headerSize: "large", editable: true, removable: true, "icon-placement": "left", onEzRemove: () => this.removeGroup(group), onEzSaveEditLabel: (event => this.handleRenameGroup(event)), onEzEditLabelMode: ({ detail }) => this.isEditingGroupName.emit(detail), conditionalSave: (newLabel) => this.canSaveGroup(newLabel, index) }, h("div", { id: this.getFieldsContainerId(group.name), class: `group-content ${!((_a = group.fields) === null || _a === void 0 ? void 0 : _a.length) ? 'empty-content' : ''}`, "data-group-name": group.name }, this.renderFields(group.fields)))));
    }));
  }
  renderFixedFields() {
    var _a, _b;
    const noGroupFields = (_b = (_a = this.groupsList.find(g => g.name === GROUP_NAMES.noGroup)) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [];
    return this.renderFields(noGroupFields);
  }
  handleRenameGuide(editDetails) {
    const { value: actualValue, newValue } = editDetails.detail;
    this.isEditGuideNameActive = false;
    if (newValue === actualValue) {
      return;
    }
    const duplicatedName = this.guideNames.includes(newValue.toLowerCase());
    const forbiddenName = this.reservedGuideNames.includes(newValue.toLowerCase());
    if (forbiddenName || duplicatedName) {
      const title = this.getMessage('snkFormConfig.confirm.title');
      const message = forbiddenName ? this.buildReservedTabNameContent(newValue) : this.buildDuplicatedTabNameContent(newValue);
      ApplicationUtils.alert(title, message).then(() => this._refTextEdit.applyFocusSelect());
      return;
    }
    this.guideRenamed.emit(newValue);
  }
  cancelEditGuideName() {
    this.isEditGuideNameActive = false;
  }
  async startGuideNameEdition() {
    this.isEditGuideNameActive = true;
    setTimeout(async () => {
      await this._refTextEdit.applyFocusSelect();
    }, 200);
  }
  getTextEditStyle() {
    return {
      fontSize: '20px',
      fontWeight: '500',
      fontFamily: 'Roboto',
    };
  }
  renderGuideName() {
    var _a, _b;
    if (this.isEditGuideNameActive) {
      return (h("div", { class: 'guide-header' }, h("ez-text-edit", { class: "collapsible-box__text-edit", ref: ref => this._refTextEdit = ref, value: (_a = this.selectedGuide) === null || _a === void 0 ? void 0 : _a.label, styled: this.getTextEditStyle(), onSaveEdition: (ev) => this.handleRenameGuide(ev), onCancelEdition: () => this.cancelEditGuideName() })));
    }
    return (h("div", { class: 'guide-header' }, h("span", { class: 'guide-header-label' }, (_b = this.selectedGuide) === null || _b === void 0 ? void 0 : _b.label), this.renderEditGuideNameButton()));
  }
  renderEditGuideNameButton() {
    var _a;
    if (((_a = this.selectedGuide) === null || _a === void 0 ? void 0 : _a.name) === TAB_NAMES.main)
      return;
    return (h("ez-button", { mode: "icon", class: "ez-button--tertiary", onClick: () => this.startGuideNameEdition(), size: "medium", iconName: 'edit', title: this.getMessage('snkFormConfig.buttons.rename') }));
  }
  setCustomCSSProperties() {
    document.documentElement.style.setProperty('--empty-content-message', `"${this.getMessage('snkFormConfig.form.labelDropField')}"`);
    document.documentElement.style.setProperty('--no-group-message', `"${this.getMessage('snkFormConfig.form.subTitleInfo')}"`);
  }
  componentDidRender() {
    this.makeGroupsDraggable();
    this.makeDynamicFieldsContainersDraggable();
    this.makeFieldContainerDraggable(GROUP_NAMES.noGroup);
    this.setCustomCSSProperties();
  }
  render() {
    if (!this.selectedGuide) {
      return (h(Host, { class: 'ez-flex-item--auto ez-size-height--full ez-box ez-padding--medium content-container' }, h("span", { class: 'no-guide-selected' }, this.getMessage('snkFormConfig.form.noGuideSelected'))));
    }
    if (this.selectedGuide.isCustom || this.selectedGuide.isDetail) {
      return (h(Host, { class: 'ez-flex-item--auto ez-size-height--full ez-box ez-padding--medium content-container' }, h("div", { class: 'message-container' }, h("h1", { class: 'no-guide-selected' }, this.getMessage('snkFormConfig.form.canNotEditCustomGuide')), h("span", { class: 'message-config-detail' }, this.getMessage('snkFormConfig.form.canNotEditDetailGuide')))));
    }
    return (h(Host, { class: 'ez-flex-item--auto ez-size-height--full ez-box ez-padding--medium content-container' }, this.renderGuideName(), h("div", { class: 'layout-container' }, h("ez-scroller", { direction: 'vertical', activeShadow: true }, h("div", { class: 'no-group-container' }, h("div", { id: GROUP_NAMES.noGroup, class: 'group-content', "data-group-name": GROUP_NAMES.noGroup }, this.renderFixedFields())), h("hr", null), h("div", { id: this.ID_GROUPS, class: 'groups-container' }, this.renderDraggableGroups()))), h("div", { class: 'add-group-container', onClick: this.handleAddGroup.bind(this) }, h("ez-icon", { slot: "leftIcon", iconName: "plus" }), h("span", null, this.getMessage('snkFormConfig.form.createNewGroup')))));
  }
  static get is() { return "fields-layout"; }
  static get encapsulation() { return "scoped"; }
  static get originalStyleUrls() {
    return {
      "$": ["fields-layout.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["fields-layout.css"]
    };
  }
  static get properties() {
    return {
      "selectedGuide": {
        "type": "unknown",
        "mutable": false,
        "complexType": {
          "original": "IGuideConfig",
          "resolved": "IGuideConfig",
          "references": {
            "IGuideConfig": {
              "location": "import",
              "path": "../FormConfigHelper"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        }
      },
      "groupsList": {
        "type": "unknown",
        "mutable": false,
        "complexType": {
          "original": "IGroupConfig[]",
          "resolved": "IGroupConfig[]",
          "references": {
            "IGroupConfig": {
              "location": "import",
              "path": "../FormConfigHelper"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "defaultValue": "[]"
      },
      "guideNames": {
        "type": "unknown",
        "mutable": false,
        "complexType": {
          "original": "string[]",
          "resolved": "string[]",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        },
        "defaultValue": "[]"
      },
      "dataUnit": {
        "type": "unknown",
        "mutable": false,
        "complexType": {
          "original": "DataUnit",
          "resolved": "DataUnit",
          "references": {
            "DataUnit": {
              "location": "import",
              "path": "@sankhyalabs/core"
            }
          }
        },
        "required": false,
        "optional": true,
        "docs": {
          "tags": [],
          "text": ""
        }
      },
      "messagesBuilder": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "SnkMessageBuilder",
          "resolved": "SnkMessageBuilder",
          "references": {
            "SnkMessageBuilder": {
              "location": "import",
              "path": "../../../lib/message/SnkMessageBuilder"
            }
          }
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": ""
        }
      }
    };
  }
  static get states() {
    return {
      "isEditGuideNameActive": {}
    };
  }
  static get events() {
    return [{
        "method": "isEditingGuideName",
        "name": "isEditingGuideName",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        }
      }, {
        "method": "isEditingGroupName",
        "name": "isEditingGroupName",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        }
      }, {
        "method": "layoutChanged",
        "name": "layoutChanged",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "IGroupConfig[]",
          "resolved": "IGroupConfig[]",
          "references": {
            "IGroupConfig": {
              "location": "import",
              "path": "../FormConfigHelper"
            }
          }
        }
      }, {
        "method": "setFieldListAsAvailable",
        "name": "setFieldListAsAvailable",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "IFieldConfig[]",
          "resolved": "IFieldConfig[]",
          "references": {
            "IFieldConfig": {
              "location": "import",
              "path": "@sankhyalabs/ezui/src/utils/interfaces/IFieldConfig"
            }
          }
        }
      }, {
        "method": "guideRenamed",
        "name": "guideRenamed",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": ""
        },
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        }
      }];
  }
  static get methods() {
    return {
      "addFieldToLayout": {
        "complexType": {
          "signature": "(incomingField: IFieldConfig) => Promise<void>",
          "parameters": [{
              "tags": [],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global"
            },
            "IFieldConfig": {
              "location": "import",
              "path": "@sankhyalabs/ezui/src/utils/interfaces/IFieldConfig"
            },
            "IGroupConfig": {
              "location": "import",
              "path": "../FormConfigHelper"
            }
          },
          "return": "Promise<void>"
        },
        "docs": {
          "text": "",
          "tags": []
        }
      }
    };
  }
  static get elementRef() { return "el"; }
  static get watchers() {
    return [{
        "propName": "messagesBuilder",
        "methodName": "onMessagesBuilderChange"
      }, {
        "propName": "selectedGuide",
        "methodName": "observeSelectedGuide"
      }, {
        "propName": "groupsList",
        "methodName": "observeGroupList"
      }, {
        "propName": "isEditGuideNameActive",
        "methodName": "observeIsEditGuideNameActive"
      }];
  }
  static get listeners() {
    return [{
        "name": "fieldConfigChanged",
        "method": "handleFieldConfigChanged",
        "target": "body",
        "capture": false,
        "passive": false
      }];
  }
}
