"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.FieldEditor = void 0;
var _react = _interopRequireWildcard(require("react"));
var _i18n = require("@kbn/i18n");
var _lodash = require("lodash");
var _eui = require("@elastic/eui");
var _shared_imports = require("../../shared_imports");
var _field_editor_context = require("../field_editor_context");
var _preview = require("../preview");
var _constants = require("./constants");
var _form_schema = require("./form_schema");
var _lib = require("./lib");
var _form_fields = require("./form_fields");
var _field_detail = require("./field_detail");
var _composite_editor = require("./composite_editor");
var _types = require("../preview/types");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

const changeWarning = _i18n.i18n.translate('indexPatternFieldEditor.editor.form.changeWarning', {
  defaultMessage: 'Changing name or type can break searches and visualizations that rely on this field.'
});
const fieldTypeToComboBoxOption = type => {
  if (type) {
    var _RUNTIME_FIELD_OPTION;
    const label = (_RUNTIME_FIELD_OPTION = _constants.RUNTIME_FIELD_OPTIONS.find(({
      value
    }) => value === type)) === null || _RUNTIME_FIELD_OPTION === void 0 ? void 0 : _RUNTIME_FIELD_OPTION.label;
    return [{
      label: label !== null && label !== void 0 ? label : type,
      value: type
    }];
  }
  return [_constants.RUNTIME_FIELD_OPTIONS[0]];
};
const formDeserializer = field => {
  const fieldType = fieldTypeToComboBoxOption(field.type);
  const format = field.format === null ? undefined : field.format;
  return {
    ...field,
    type: fieldType,
    format,
    __meta__: {
      isCustomLabelVisible: field.customLabel !== undefined,
      isValueVisible: field.script !== undefined,
      isFormatVisible: field.format !== undefined,
      isPopularityVisible: field.popularity !== undefined
    }
  };
};
const formSerializer = field => {
  const {
    __meta__,
    type,
    format,
    ...rest
  } = field;
  return {
    type: type && type[0].value,
    // By passing "null" we are explicitly telling DataView to remove the
    // format if there is one defined for the field.
    format: format === undefined ? null : format,
    ...rest
  };
};
const FieldEditorComponent = ({
  field,
  onChange,
  onFormModifiedChange
}) => {
  var _ref, _ref2;
  const {
    namesNotAllowed,
    fieldTypeToProcess,
    fieldName$,
    subfields$
  } = (0, _field_editor_context.useFieldEditorContext)();
  const {
    params: {
      update: updatePreviewParams
    },
    fieldPreview$
  } = (0, _preview.useFieldPreviewContext)();
  const {
    form
  } = (0, _shared_imports.useForm)({
    defaultValue: field,
    schema: _form_schema.schema,
    deserializer: formDeserializer,
    serializer: formSerializer
  });
  const {
    submit,
    isValid: isFormValid,
    isSubmitted,
    getFields,
    isSubmitting
  } = form;
  const nameFieldConfig = (0, _lib.getNameFieldConfig)(namesNotAllowed, field);
  const [formData] = (0, _shared_imports.useFormData)({
    form
  });
  const isFormModified = (0, _shared_imports.useFormIsModified)({
    form,
    discard: ['__meta__.isCustomLabelVisible', '__meta__.isValueVisible', '__meta__.isFormatVisible', '__meta__.isPopularityVisible']
  });

  // use observable to sidestep react state
  (0, _react.useEffect)(() => {
    const sub = form.subscribe(({
      data
    }) => {
      if (data.internal.name !== fieldName$.getValue()) {
        fieldName$.next(data.internal.name);
      }
    });
    return () => {
      sub.unsubscribe();
    };
  }, [form, fieldName$]);
  const {
    name: updatedName,
    type: updatedType,
    script: updatedScript,
    format: updatedFormat
  } = formData;
  const {
    name: nameField,
    type: typeField
  } = getFields();
  const nameHasChanged = (_ref = Boolean(field === null || field === void 0 ? void 0 : field.name) && (nameField === null || nameField === void 0 ? void 0 : nameField.isModified)) !== null && _ref !== void 0 ? _ref : false;
  const typeHasChanged = (_ref2 = Boolean(field === null || field === void 0 ? void 0 : field.type) && (typeField === null || typeField === void 0 ? void 0 : typeField.isModified)) !== null && _ref2 !== void 0 ? _ref2 : false;
  const isValueVisible = (0, _lodash.get)(formData, '__meta__.isValueVisible');
  const resetTypes = (0, _react.useCallback)(() => {
    const lastVal = fieldPreview$.getValue();
    // resets the preview history to an empty set
    fieldPreview$.next([]);
    // apply the last preview to get all the types
    fieldPreview$.next(lastVal);
  }, [fieldPreview$]);
  (0, _react.useEffect)(() => {
    const existingCompositeField = !!Object.keys(subfields$.getValue() || {}).length;
    const changes$ = (0, _lib.getFieldPreviewChanges)(fieldPreview$, updatedName);
    const subChanges = changes$.subscribe(previewFields => {
      const fields = subfields$.getValue();
      const modifiedFields = {
        ...fields
      };
      Object.entries(previewFields).forEach(([name, change]) => {
        if (change.changeType === _types.ChangeType.DELETE) {
          delete modifiedFields[name];
        }
        if (change.changeType === _types.ChangeType.UPSERT) {
          modifiedFields[name] = {
            type: change.type
          };
        }
      });
      subfields$.next(modifiedFields);
      // necessary to maintain script code when changing types
      form.updateFieldValues({
        ...form.getFormData()
      });
    });

    // first preview value is skipped for saved fields, need to populate for new fields and rerenders
    if (!existingCompositeField) {
      fieldPreview$.next([]);
    } else if (fieldPreview$.getValue()) {
      fieldPreview$.next(fieldPreview$.getValue());
    }
    return () => {
      subChanges.unsubscribe();
    };
  }, [form, fieldPreview$, subfields$, updatedName]);
  (0, _react.useEffect)(() => {
    if (onChange) {
      onChange({
        isValid: isFormValid,
        isSubmitted,
        isSubmitting,
        submit
      });
    }
  }, [onChange, isFormValid, isSubmitted, isSubmitting, submit]);
  (0, _react.useEffect)(() => {
    updatePreviewParams({
      name: Boolean(updatedName === null || updatedName === void 0 ? void 0 : updatedName.trim()) ? updatedName : null,
      type: updatedType === null || updatedType === void 0 ? void 0 : updatedType[0].value,
      script: isValueVisible === false || Boolean(updatedScript === null || updatedScript === void 0 ? void 0 : updatedScript.source.trim()) === false ? null : {
        source: updatedScript.source
      },
      format: (updatedFormat === null || updatedFormat === void 0 ? void 0 : updatedFormat.id) !== undefined ? updatedFormat : null,
      parentName: field === null || field === void 0 ? void 0 : field.parentName
    });
  }, [updatedName, updatedType, updatedScript, isValueVisible, updatedFormat, updatePreviewParams, field]);
  (0, _react.useEffect)(() => {
    if (onFormModifiedChange) {
      onFormModifiedChange(isFormModified);
    }
  }, [isFormModified, onFormModifiedChange, form]);
  return /*#__PURE__*/_react.default.createElement(_shared_imports.Form, {
    form: form,
    className: "indexPatternFieldEditor__form",
    "data-test-subj": "indexPatternFieldEditorForm",
    isInvalid: isSubmitted && isFormValid === false,
    error: form.getErrors()
  }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_shared_imports.UseField, {
    path: "name",
    config: nameFieldConfig,
    component: _shared_imports.TextField,
    "data-test-subj": "nameField",
    componentProps: {
      euiFieldProps: {
        disabled: fieldTypeToProcess === 'concrete',
        'aria-label': _i18n.i18n.translate('indexPatternFieldEditor.editor.form.nameAriaLabel', {
          defaultMessage: 'Name field'
        })
      }
    }
  })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_form_fields.TypeField, {
    isDisabled: fieldTypeToProcess === 'concrete',
    includeComposite: true,
    path: "type"
  }))), (nameHasChanged || typeHasChanged) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, {
    size: "xs"
  }), /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, {
    color: "warning",
    title: changeWarning,
    iconType: "warning",
    size: "s",
    "data-test-subj": "changeWarning"
  })), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, {
    size: "xl"
  }), (field === null || field === void 0 ? void 0 : field.parentName) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, {
    iconType: "iInCircle",
    title: _i18n.i18n.translate('indexPatternFieldEditor.editor.form.subFieldParentInfo', {
      defaultMessage: "Field value is defined by '{parentName}'",
      values: {
        parentName: field === null || field === void 0 ? void 0 : field.parentName
      }
    })
  }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, {
    size: "xl"
  })), updatedType && updatedType[0].value !== 'composite' ? /*#__PURE__*/_react.default.createElement(_field_detail.FieldDetail, null) : /*#__PURE__*/_react.default.createElement(_composite_editor.CompositeEditor, {
    onReset: resetTypes
  }));
};
const FieldEditor = FieldEditorComponent;
exports.FieldEditor = FieldEditor;