import { __rest } from "tslib";
import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable no-console */

import React from 'react';
import clsx from 'clsx';
import { Field as RcField } from 'rc-field-form';
import { FieldContext } from 'rc-field-form';
import Field from '../field';
import { toArray } from '../uploader/utils';
import { FIELD_KEY } from '../field/Field';
import { COMPONENT_TYPE_KEY } from '../utils/constant';
import { FormContext } from './FormContext';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';
import { devWarning } from '../utils/dev-log';
const MemoInput = React.memo(_a => {
  var {
    children
  } = _a,
      props = __rest(_a, ["children"]);

  return React.cloneElement(children, props);
}, (prev, next) => prev.value === next.value && prev.update === next.update);

const FormItemLayout = props => {
  const {
    className,
    meta,
    children,
    isFieldChildren,
    showValidateMessage,
    colon,
    layout,
    labelAlign,
    inputAlign,
    border
  } = props,
        fieldProps = __rest(props, ["className", "meta", "children", "isFieldChildren", "showValidateMessage", "colon", "layout", "labelAlign", "inputAlign", "border"]);

  const {
    prefixCls,
    createNamespace
  } = React.useContext(ConfigProviderContext);
  const [bem] = createNamespace('form', prefixCls);
  const context = React.useContext(FormContext);
  const itemLayout = layout !== null && layout !== void 0 ? layout : context.layout;
  const itemBorder = border !== null && border !== void 0 ? border : context.border;
  const itemColon = colon !== null && colon !== void 0 ? colon : context.colon;
  const itemShowValidateMessage = showValidateMessage !== null && showValidateMessage !== void 0 ? showValidateMessage : context.showValidateMessage;
  const itemLabelAlign = labelAlign !== null && labelAlign !== void 0 ? labelAlign : context.labelAlign;
  const itemInputAlign = inputAlign !== null && inputAlign !== void 0 ? inputAlign : context.inputAlign;
  const error = meta && meta.errors.length > 0;
  const errorMessage = itemShowValidateMessage && error ? meta.errors[0] : null;
  const attrs = Object.assign(Object.assign({}, fieldProps), {
    className: clsx(bem({
      vertical: itemLayout === 'vertical'
    }), className),
    colon: itemColon,
    error,
    errorMessage,
    labelAlign: itemLabelAlign,
    inputAlign: itemInputAlign,
    border: itemBorder
  });
  if (isFieldChildren) return React.cloneElement(children, attrs);
  return _jsx(Field, Object.assign({}, attrs, {
    children: children
  }));
};

const FormItem = props => {
  var _a;

  const {
    className,
    style,
    label,
    name,
    required,
    noStyle,
    tooltip,
    intro,
    customField,
    disabled,
    colon,
    rules,
    children,
    messageVariables,
    trigger = 'onChange',
    validateTrigger,
    onClick,
    shouldUpdate,
    dependencies,
    labelWidth,
    labelAlign,
    labelClass,
    showValidateMessage,
    inputAlign,
    errorMessageAlign,
    border,
    layout
  } = props,
        fieldProps = __rest(props, ["className", "style", "label", "name", "required", "noStyle", "tooltip", "intro", "customField", "disabled", "colon", "rules", "children", "messageVariables", "trigger", "validateTrigger", "onClick", "shouldUpdate", "dependencies", "labelWidth", "labelAlign", "labelClass", "showValidateMessage", "inputAlign", "errorMessageAlign", "border", "layout"]);

  const {
    validateTrigger: contextValidateTrigger
  } = React.useContext(FieldContext);
  const mergedValidateTrigger = validateTrigger !== undefined ? validateTrigger : contextValidateTrigger;
  const updateRef = React.useRef(0);
  updateRef.current += 1;
  const isFieldChildren = ((_a = children.type) === null || _a === void 0 ? void 0 : _a[COMPONENT_TYPE_KEY]) === FIELD_KEY || customField;

  function renderLayout(baseChildren, fieldId, meta, isRequired) {
    if (noStyle) {
      return baseChildren;
    }

    return _jsx(FormItemLayout, Object.assign({
      isFieldChildren: isFieldChildren,
      className: className,
      style: style,
      label: label,
      tooltip: tooltip,
      intro: intro,
      required: isRequired,
      disabled: disabled,
      htmlFor: fieldId,
      meta: meta,
      colon: colon,
      border: border,
      layout: layout,
      labelWidth: labelWidth,
      labelAlign: labelAlign,
      labelClass: labelClass,
      inputAlign: inputAlign,
      errorMessageAlign: errorMessageAlign,
      showValidateMessage: showValidateMessage,
      onClick: onClick
    }, {
      children: baseChildren
    }));
  }

  const isRenderProps = typeof children === 'function';

  if (!name && !isRenderProps && !props.dependencies) {
    return renderLayout(children);
  }

  let variables = {};

  if (typeof label === 'string') {
    variables.label = label;
  }

  if (messageVariables) {
    variables = Object.assign(Object.assign({}, variables), messageVariables);
  }

  return _jsx(RcField, Object.assign({}, fieldProps, {
    name: name,
    shouldUpdate: shouldUpdate,
    dependencies: dependencies,
    rules: rules,
    trigger: trigger,
    validateTrigger: mergedValidateTrigger
  }, {
    children: (control, meta, context) => {
      var _a;

      let childNode = null;
      const isRequired = required !== undefined ? required : !!(rules && rules.some(rule => {
        if (rule && typeof rule === 'object' && rule.required) {
          return true;
        }

        return false;
      }));
      const fieldId = (toArray(name).length && meta ? meta.name : []).join('_');

      if (shouldUpdate && dependencies) {
        devWarning('Form.Item', "`shouldUpdate` and `dependencies` shouldn't be used together.");
      }

      if (isRenderProps) {
        if ((shouldUpdate || dependencies) && !name) {
          childNode = children(context);
        } else {
          if (!(shouldUpdate || dependencies)) {
            devWarning('Form.Item', '`children` of render props only work with `shouldUpdate` or `dependencies`.');
          }

          if (name) {
            devWarning('Form.Item', "Do not use `name` with `children` of render props since it's not a field.");
          }
        } // not render props

      } else if (dependencies && !name) {
        devWarning('Form.Item', 'Must set `name` or use render props when `dependencies` is set.');
      } else if (React.isValidElement(children)) {
        const childProps = Object.assign(Object.assign({}, children.props), control);

        if (!childProps.id) {
          childProps.id = fieldId;
        }

        if (disabled) {
          childProps.disabled = disabled;
        } // We should keep user origin event handler


        const triggers = new Set([...toArray(trigger), ...toArray(mergedValidateTrigger)]);
        triggers.forEach(eventName => {
          childProps[eventName] = (...args) => {
            var _a, _b, _c;

            (_a = control[eventName]) === null || _a === void 0 ? void 0 : _a.call(control, ...args);
            (_c = (_b = children.props)[eventName]) === null || _c === void 0 ? void 0 : _c.call(_b, ...args);
          };
        });
        childNode = _jsx(MemoInput, Object.assign({
          value: control[props.valuePropName || 'value'],
          update: updateRef.current
        }, {
          children: React.cloneElement(children, childProps)
        }));

        if (isFieldChildren) {
          childProps.value = (_a = childProps.value) !== null && _a !== void 0 ? _a : '';
          childNode = React.cloneElement(children, childProps);
        }
      } else {
        if (name) {
          devWarning('Form.Item', '`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.');
        }

        childNode = children;
      }

      return renderLayout(childNode, fieldId, meta, isRequired);
    }
  }));
};

export default FormItem;