import { DataType, UserInterface } from '@sankhyalabs/core';
import { DEFAULT_TYPE, GROUP_NAMES, TAB_NAMES } from '../../lib/utils/constants';
const iconMap = new Map([
  [UserInterface.DATE, 'calendar'],
  [UserInterface.DATETIME, 'calendar-clock'],
  [UserInterface.ELAPSEDTIME, 'timer-outline'],
  [UserInterface.TIME, 'timer-outline'],
  [UserInterface.DECIMALNUMBER, 'number'],
  [UserInterface.INTEGERNUMBER, 'number'],
  [UserInterface.FILE, 'zip'],
  [UserInterface.IMAGE, 'pdf'],
  [UserInterface.HTML, 'tag_code'],
  [UserInterface.SEARCH, 'search'],
  [UserInterface.SEARCHPLUS, 'search'],
  [UserInterface.OPTIONSELECTOR, 'list'],
  [UserInterface.CHECKBOX, 'list'],
  [UserInterface.SWITCH, 'boolean'],
  [UserInterface.PASSWORD, 'eye-off'],
]);
export const ID_AVAILABLE_FIELDS = 'container-available-fields';
export var SORTABLE_PATH;
(function (SORTABLE_PATH) {
  SORTABLE_PATH["FROM"] = "from";
  SORTABLE_PATH["TO"] = "to";
})(SORTABLE_PATH || (SORTABLE_PATH = {}));
export function getFieldsStructure(evt, path, group, tab) {
  var _a;
  const htmlStructure = (_a = evt === null || evt === void 0 ? void 0 : evt[path]) === null || _a === void 0 ? void 0 : _a.children;
  if (!htmlStructure)
    return [];
  return Array.from(htmlStructure).map(({ fieldConfig }) => {
    return Object.assign(Object.assign({}, fieldConfig), { group, tab });
  });
}
export function updateTabInFieldsFromGroupList(guideGroups, updatedName) {
  return guideGroups.map(group => {
    return Object.assign(Object.assign({}, group), { fields: group.fields.map(field => (Object.assign(Object.assign({}, field), { tab: updatedName }))) });
  });
}
export function getValidatedFieldValue(fieldValue, dataUnit, fieldName) {
  var _a;
  if (fieldValue == undefined || !dataUnit || !fieldName)
    return;
  const dataType = (_a = dataUnit.getField(fieldName)) === null || _a === void 0 ? void 0 : _a.dataType;
  if (dataType == undefined)
    return;
  if ((fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.waitmessage) !== undefined)
    return undefined;
  const isNonObjectValue = dataType !== DataType.OBJECT &&
    dataType !== DataType.DATE &&
    typeof fieldValue === 'object';
  const processedValue = isNonObjectValue ? fieldValue.value : fieldValue;
  return dataType === DataType.OBJECT
    ? JSON.stringify(processedValue)
    : processedValue;
}
export function getEnabledByProperty(attribName, propertyName, fieldDescriptor) {
  if (!fieldDescriptor)
    return true;
  const fieldProperties = fieldDescriptor.properties || {};
  const fromAttribName = fieldDescriptor[attribName] !== true;
  return fieldProperties.hasOwnProperty(propertyName)
    ? fieldProperties[propertyName] !== 'S'
    : fromAttribName;
}
export function getValueByProperty(property, fieldDescriptor, defaultValue) {
  if (fieldDescriptor && fieldDescriptor[property] === true) {
    return true;
  }
  return defaultValue;
}
export function getIconName(userInterface) {
  return iconMap.get(userInterface) || 'text';
}
export function buildNewGuideName(guidesList, getMessage) {
  var _a, _b;
  const newGuideText = getMessage('snkFormConfig.form.newGuide');
  const qtdWithNewGuideName = (_b = (_a = guidesList.filter(g => g.name.includes(newGuideText))) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
  return qtdWithNewGuideName === 0 ? newGuideText : `${newGuideText} (${qtdWithNewGuideName})`;
}
export function getFieldsToSave(guidesMap) {
  const fieldsToSave = [];
  guidesMap.forEach(groups => {
    groups.forEach(({ fields }) => {
      fields === null || fields === void 0 ? void 0 : fields.forEach((fieldConfig) => {
        fieldsToSave.push(buildFieldToSave(fieldConfig));
      });
    });
  });
  return fieldsToSave;
}
export function buildGuidesMap(rawFields, tabs, dataUnit, generalTab) {
  const fields = handleFieldsTabNames(rawFields);
  const guidesMap = initGuidesMap(tabs);
  if (!(fields === null || fields === void 0 ? void 0 : fields.length))
    return;
  for (let guideName of guidesMap.keys()) {
    const fieldsFromGuide = getFieldsFromGuide(fields, guideName, generalTab);
    const fieldsByGroupMap = getGroupsFromGuide(fieldsFromGuide, dataUnit, generalTab);
    const groupsList = parserGroupMapIntoList(fieldsByGroupMap);
    guidesMap.set(guideName, groupsList);
  }
  return guidesMap;
}
export function buildGuides(config, mainArea) {
  let tabs = config.tabs ? [...config.tabs] : buildTabsFromFields(config === null || config === void 0 ? void 0 : config.fields);
  tabs = getPossibleGuides(tabs);
  tabs = initializeTabsNames(tabs);
  return handleMainTab(tabs, mainArea);
}
export function buildChildrenGuides(dataUnit, initialOrderIndex = 0, guidesList) {
  var _a;
  if (!dataUnit || !dataUnit.metadata) {
    return [];
  }
  const children = ((_a = dataUnit.metadata) === null || _a === void 0 ? void 0 : _a.children) || [];
  const childrenWithNoGuide = [];
  for (const child of children) {
    const guideOnConfig = guidesList.find(guide => child.label === guide.label);
    if (guideOnConfig) {
      guideOnConfig.isCustom = true;
      continue;
    }
    childrenWithNoGuide.push({
      label: child.label,
      name: child.name,
      visible: true,
      isCustom: true,
      order: initialOrderIndex++,
    });
  }
  return childrenWithNoGuide;
}
function handleFieldsTabNames(allFields) {
  // Campos que não fazem parte de nenhuma aba ou da aba "Geral", devem ser movidos para a aba __main.
  return allFields.map(field => {
    const tabName = field.tab;
    return Object.assign(Object.assign({}, field), { tab: (!tabName || tabName === TAB_NAMES.general) ? TAB_NAMES.main : field.tab });
  });
}
function initializeTabsNames(tabs) {
  return tabs.map((tab) => {
    return Object.assign(Object.assign({}, tab), { name: tab.name ? tab.name : tab.label });
  });
}
function handleMainTab(tabs, mainTabName) {
  const mainTab = { name: TAB_NAMES.main, label: mainTabName, visible: true };
  const hasTabMain = tabs.some((tab) => tab.name === TAB_NAMES.main);
  if (hasTabMain) {
    tabs = tabs.map(tab => tab.name === TAB_NAMES.main ? mainTab : tab);
  }
  else {
    tabs.unshift(mainTab);
  }
  return tabs;
}
function getPossibleGuides(tabs) {
  //O usuário não pode criar uma guia com o nome "Geral".
  // Nesses casos, precisamos mover os campos dessa guia, para a guia __main.
  return [...tabs.filter(tab => tab.label !== TAB_NAMES.general)];
}
function initGuidesMap(tabs) {
  const map = new Map();
  let possibleGuides = getPossibleGuides(tabs);
  possibleGuides.forEach(tab => {
    map.set(tab.name, []);
  });
  return map;
}
function handleFieldLabel(field, fieldDescriptor) {
  if (!field.label) {
    field.label = fieldDescriptor.label;
  }
}
function handleFieldTab(field, generalTabName) {
  if (!field.tab) {
    field.tab = generalTabName;
  }
}
function handleFieldGroup(field) {
  if (!field.group) {
    field.group = GROUP_NAMES.noGroup;
  }
}
function isVisibleOnConfig(fieldDescriptor) {
  var _a;
  /**
   * Quando um campo é ocultado pelo dev, mas queremos manter ele na config precisamos fazer essa tratativa.
   */
  return ((_a = fieldDescriptor === null || fieldDescriptor === void 0 ? void 0 : fieldDescriptor.properties) === null || _a === void 0 ? void 0 : _a.visibleOnConfig) === true && (fieldDescriptor === null || fieldDescriptor === void 0 ? void 0 : fieldDescriptor.visible) === false;
}
function getGroupsFromGuide(fieldsFromGuide, dataUnit, generalTabName) {
  const groupsMap = new Map();
  groupsMap.set(GROUP_NAMES.noGroup, []);
  for (let field of fieldsFromGuide) {
    const fieldDescriptor = dataUnit.getField(field.name);
    if (!(fieldDescriptor === null || fieldDescriptor === void 0 ? void 0 : fieldDescriptor.visible) && !isVisibleOnConfig(fieldDescriptor))
      continue;
    handleFieldLabel(field, fieldDescriptor);
    handleFieldTab(field, generalTabName);
    handleFieldGroup(field);
    if (groupsMap.has(field.group)) {
      groupsMap.get(field.group).push(field);
    }
    else {
      groupsMap.set(field.group, [field]);
    }
  }
  return groupsMap;
}
function getFieldsFromGuide(fields, guideName, generalTabName) {
  return fields.filter(field => {
    const fieldTab = getTabName(field.tab, generalTabName);
    return fieldTab === guideName;
  });
}
function getTabName(tab, generalTabName) {
  var _a;
  if (typeof tab === 'string')
    return tab;
  return (_a = tab === null || tab === void 0 ? void 0 : tab.label) !== null && _a !== void 0 ? _a : generalTabName;
}
function parserGroupMapIntoList(groupsMap) {
  const groupsList = [];
  for (let groupName of groupsMap.keys()) {
    groupsList.push({ name: groupName, fields: groupsMap.get(groupName) });
  }
  return groupsList;
}
function canAddTab(tab, guideList) {
  return tab && !(guideList.map(g => g.name).includes(tab));
}
function buildTabsFromFields(fields) {
  const guideList = [];
  let order = 1;
  fields === null || fields === void 0 ? void 0 : fields.forEach((field) => {
    const tab = field.tab;
    if (canAddTab(tab, guideList)) {
      guideList.push({ name: tab, label: tab, visible: true, order });
      order = order + 1;
    }
  });
  return guideList;
}
function buildFieldToSave(fieldConfig) {
  const fieldToSave = {
    cleanOnCopy: fieldConfig.cleanOnCopy || false,
    group: fieldConfig.group === GROUP_NAMES.noGroup ? undefined : fieldConfig.group,
    label: fieldConfig.label,
    name: fieldConfig.name,
    required: fieldConfig.required,
    readOnly: fieldConfig.readOnly,
    tab: fieldConfig.tab,
  };
  if (fieldConfig.defaultValue != undefined) {
    if (fieldConfig.defaultValue.type == undefined) {
      fieldToSave.defaultValue = {
        type: DEFAULT_TYPE.fixed,
        value: fieldConfig.defaultValue,
      };
    }
    else {
      fieldToSave.defaultValue = fieldConfig.defaultValue;
    }
  }
  return fieldToSave;
}
