import * as _vue from "vue";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

import { inject, provide, Transition } from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import getTransitionProps from '../_util/getTransitionProps';
import Row from '../grid/Row';
import Col, { ColProps } from '../grid/Col';
import hasProp, { initDefaultProps, findDOMNode, getComponent, getOptionProps, getEvents, isValidElement, getSlot } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin';
import { ConfigConsumerProps } from '../config-provider';
import { cloneElement } from '../_util/vnode';
import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import { validateRules as _validateRules } from './utils/validateUtil';
import { getNamePath } from './utils/valueUtil';
import { toArray } from './utils/typeUtil';
import { warning } from '../vc-util/warning';
import find from 'lodash/find';
var iconMap = {
  success: CheckCircleFilled,
  warning: ExclamationCircleFilled,
  error: CloseCircleFilled,
  validating: LoadingOutlined
};

function getPropByPath(obj, namePathList, strict) {
  var tempObj = obj;
  var keyArr = namePathList;
  var i = 0;

  try {
    for (var len = keyArr.length; i < len - 1; ++i) {
      if (!tempObj && !strict) break;
      var key = keyArr[i];

      if (key in tempObj) {
        tempObj = tempObj[key];
      } else {
        if (strict) {
          throw Error('please transfer a valid name path to form item!');
        }

        break;
      }
    }

    if (strict && !tempObj) {
      throw Error('please transfer a valid name path to form item!');
    }
  } catch (error) {
    console.error('please transfer a valid name path to form item!');
  }

  return {
    o: tempObj,
    k: keyArr[i],
    v: tempObj ? tempObj[keyArr[i]] : undefined
  };
}

export var FormItemProps = {
  id: PropTypes.string,
  htmlFor: PropTypes.string,
  prefixCls: PropTypes.string,
  label: PropTypes.any,
  help: PropTypes.any,
  extra: PropTypes.any,
  labelCol: PropTypes.shape(ColProps).loose,
  wrapperCol: PropTypes.shape(ColProps).loose,
  hasFeedback: PropTypes.bool,
  colon: PropTypes.bool,
  labelAlign: PropTypes.oneOf(['left', 'right']),
  prop: PropTypes.oneOfType([Array, String, Number]),
  name: PropTypes.oneOfType([Array, String, Number]),
  rules: PropTypes.oneOfType([Array, Object]),
  autoLink: PropTypes.bool,
  required: PropTypes.bool,
  validateFirst: PropTypes.bool,
  validateStatus: PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']),
  validateTrigger: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
};
export default {
  name: 'AFormItem',
  mixins: [BaseMixin],
  inheritAttrs: false,
  __ANT_NEW_FORM_ITEM: true,
  props: initDefaultProps(FormItemProps, {
    hasFeedback: false,
    autoLink: true
  }),
  setup: function setup() {
    return {
      isFormItemChildren: inject('isFormItemChildren', false),
      configProvider: inject('configProvider', ConfigConsumerProps),
      FormContext: inject('FormContext', {})
    };
  },
  data: function data() {
    warning(!hasProp(this, 'prop'), "`prop` is deprecated. Please use `name` instead.");
    return {
      validateState: this.validateStatus,
      validateMessage: '',
      validateDisabled: false,
      validator: {},
      helpShow: false,
      errors: []
    };
  },
  computed: {
    fieldName: function fieldName() {
      return this.name || this.prop;
    },
    namePath: function namePath() {
      return getNamePath(this.fieldName);
    },
    fieldId: function fieldId() {
      if (this.id) {
        return this.id;
      } else if (!this.namePath.length) {
        return undefined;
      } else {
        var formName = this.FormContext.name;
        var mergedId = this.namePath.join('_');
        return formName ? "".concat(formName, "_").concat(mergedId) : mergedId;
      }
    },
    fieldValue: function fieldValue() {
      var model = this.FormContext.model;

      if (!model || !this.fieldName) {
        return;
      }

      return getPropByPath(model, this.namePath, true).v;
    },
    isRequired: function isRequired() {
      var rules = this.getRules();
      var isRequired = false;

      if (rules && rules.length) {
        rules.every(function (rule) {
          if (rule.required) {
            isRequired = true;
            return false;
          }

          return true;
        });
      }

      return isRequired || this.required;
    },
    mergedValidateTrigger: function mergedValidateTrigger() {
      var validateTrigger = this.validateTrigger !== undefined ? this.validateTrigger : this.FormContext.validateTrigger;
      validateTrigger = validateTrigger === undefined ? 'change' : validateTrigger;
      return toArray(validateTrigger);
    }
  },
  watch: {
    validateStatus: function validateStatus(val) {
      this.validateState = val;
    }
  },
  created: function created() {
    provide('isFormItemChildren', true);
  },
  mounted: function mounted() {
    if (this.fieldName) {
      var addField = this.FormContext.addField;
      addField && addField(this);
      this.initialValue = cloneDeep(this.fieldValue);
    }
  },
  beforeUnmount: function beforeUnmount() {
    var removeField = this.FormContext.removeField;
    removeField && removeField(this);
  },
  methods: {
    getNamePath: function getNamePath() {
      var fieldName = this.fieldName;
      var _this$FormContext$pre = this.FormContext.prefixName,
          prefixName = _this$FormContext$pre === void 0 ? [] : _this$FormContext$pre;
      return fieldName !== undefined ? [].concat(_toConsumableArray(prefixName), _toConsumableArray(this.namePath)) : [];
    },
    validateRules: function validateRules(options) {
      var _this = this;

      var _this$$props = this.$props,
          _this$$props$validate = _this$$props.validateFirst,
          validateFirst = _this$$props$validate === void 0 ? false : _this$$props$validate,
          messageVariables = _this$$props.messageVariables;

      var _ref = options || {},
          triggerName = _ref.triggerName;

      var namePath = this.getNamePath();
      var filteredRules = this.getRules();

      if (triggerName) {
        filteredRules = filteredRules.filter(function (rule) {
          var trigger = rule.trigger;

          if (!trigger && !_this.mergedValidateTrigger.length) {
            return true;
          }

          var triggerList = toArray(trigger || _this.mergedValidateTrigger);
          return triggerList.includes(triggerName);
        });
      }

      if (!filteredRules.length) {
        return Promise.resolve();
      }

      var promise = _validateRules(namePath, this.fieldValue, filteredRules, options, validateFirst, messageVariables);

      this.validateState = 'validating';
      this.errors = [];
      promise.catch(function (e) {
        return e;
      }).then(function () {
        var errors = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];

        if (_this.validateState === 'validating') {
          _this.validateState = errors.length ? 'error' : 'success';
          _this.validateMessage = errors[0];
          _this.errors = errors;
        }
      });
      return promise;
    },
    getRules: function getRules() {
      var formRules = this.FormContext.rules;
      var selfRules = this.rules;
      var requiredRule = this.required !== undefined ? {
        required: !!this.required,
        trigger: this.mergedValidateTrigger
      } : [];
      var prop = getPropByPath(formRules, this.namePath);
      formRules = formRules ? prop.o[prop.k] || prop.v : [];
      var rules = [].concat(selfRules || formRules || []);

      if (find(rules, function (rule) {
        return rule.required;
      })) {
        return rules;
      } else {
        return rules.concat(requiredRule);
      }
    },
    onFieldBlur: function onFieldBlur() {
      this.validateRules({
        triggerName: 'blur'
      });
    },
    onFieldChange: function onFieldChange() {
      if (this.validateDisabled) {
        this.validateDisabled = false;
        return;
      }

      this.validateRules({
        triggerName: 'change'
      });
    },
    clearValidate: function clearValidate() {
      this.validateState = '';
      this.validateMessage = '';
      this.validateDisabled = false;
    },
    resetField: function resetField() {
      var _this2 = this;

      this.validateState = '';
      this.validateMessage = '';
      var model = this.FormContext.model || {};
      var value = this.fieldValue;
      var prop = getPropByPath(model, this.namePath, true);
      this.validateDisabled = true;

      if (Array.isArray(value)) {
        prop.o[prop.k] = [].concat(this.initialValue);
      } else {
        prop.o[prop.k] = this.initialValue;
      } // reset validateDisabled after onFieldChange triggered


      this.$nextTick(function () {
        _this2.validateDisabled = false;
      });
    },
    getHelpMessage: function getHelpMessage() {
      var help = getComponent(this, 'help');
      return this.validateMessage || help;
    },
    onLabelClick: function onLabelClick() {
      var id = this.fieldId;

      if (!id) {
        return;
      }

      var formItemNode = findDOMNode(this);
      var control = formItemNode.querySelector("[id=\"".concat(id, "\"]"));

      if (control && control.focus) {
        control.focus();
      }
    },
    onHelpAnimEnd: function onHelpAnimEnd(_key, helpShow) {
      this.helpShow = helpShow;

      if (!helpShow) {
        this.$forceUpdate();
      }
    },
    renderHelp: function renderHelp(prefixCls) {
      var _this3 = this;

      var help = this.getHelpMessage();
      var children = help ? _vue.createVNode("div", {
        "class": "".concat(prefixCls, "-explain"),
        "key": "help"
      }, [help]) : null;

      if (children) {
        this.helpShow = !!children;
      }

      var transitionProps = getTransitionProps('show-help', {
        onAfterEnter: function onAfterEnter() {
          return _this3.onHelpAnimEnd('help', true);
        },
        onAfterLeave: function onAfterLeave() {
          return _this3.onHelpAnimEnd('help', false);
        }
      });
      return _vue.createVNode(Transition, _vue.mergeProps(transitionProps, {
        "key": "help"
      }), {
        default: function _default() {
          return [children];
        }
      });
    },
    renderExtra: function renderExtra(prefixCls) {
      var extra = getComponent(this, 'extra');
      return extra ? _vue.createVNode("div", {
        "class": "".concat(prefixCls, "-extra")
      }, [extra]) : null;
    },
    renderValidateWrapper: function renderValidateWrapper(prefixCls, c1, c2, c3) {
      var validateStatus = this.validateState;
      var classes = "".concat(prefixCls, "-item-control");

      if (validateStatus) {
        classes = classNames("".concat(prefixCls, "-item-control"), {
          'has-feedback': this.hasFeedback || validateStatus === 'validating',
          'has-success': validateStatus === 'success',
          'has-warning': validateStatus === 'warning',
          'has-error': validateStatus === 'error',
          'is-validating': validateStatus === 'validating'
        });
      }

      var IconNode = validateStatus && iconMap[validateStatus];
      var icon = this.hasFeedback && IconNode ? _vue.createVNode("span", {
        "class": "".concat(prefixCls, "-item-children-icon")
      }, [_vue.createVNode(IconNode, null, null)]) : null;
      return _vue.createVNode("div", {
        "class": classes
      }, [_vue.createVNode("span", {
        "class": "".concat(prefixCls, "-item-children")
      }, [c1, icon]), c2, c3]);
    },
    renderWrapper: function renderWrapper(prefixCls, children) {
      var _ref2 = this.isFormItemChildren ? {} : this.FormContext,
          contextWrapperCol = _ref2.wrapperCol;

      var wrapperCol = this.wrapperCol;
      var mergedWrapperCol = wrapperCol || contextWrapperCol || {};

      var style = mergedWrapperCol.style,
          id = mergedWrapperCol.id,
          restProps = _objectWithoutProperties(mergedWrapperCol, ["style", "id"]);

      var className = classNames("".concat(prefixCls, "-item-control-wrapper"), mergedWrapperCol.class);

      var colProps = _objectSpread(_objectSpread({}, restProps), {}, {
        class: className,
        key: 'wrapper',
        style: style,
        id: id
      });

      return _vue.createVNode(Col, colProps, {
        default: function _default() {
          return [children];
        }
      });
    },
    renderLabel: function renderLabel(prefixCls) {
      var _classNames,
          _this4 = this;

      var _this$FormContext = this.FormContext,
          vertical = _this$FormContext.vertical,
          contextLabelAlign = _this$FormContext.labelAlign,
          contextLabelCol = _this$FormContext.labelCol,
          contextColon = _this$FormContext.colon;
      var labelAlign = this.labelAlign,
          labelCol = this.labelCol,
          colon = this.colon,
          fieldId = this.fieldId,
          htmlFor = this.htmlFor;
      var label = getComponent(this, 'label');
      var required = this.isRequired;
      var mergedLabelCol = labelCol || contextLabelCol || {};
      var mergedLabelAlign = labelAlign || contextLabelAlign;
      var labelClsBasic = "".concat(prefixCls, "-item-label");
      var labelColClassName = classNames(labelClsBasic, mergedLabelAlign === 'left' && "".concat(labelClsBasic, "-left"), mergedLabelCol.class);

      var labelColClass = mergedLabelCol.class,
          labelColStyle = mergedLabelCol.style,
          labelColId = mergedLabelCol.id,
          restProps = _objectWithoutProperties(mergedLabelCol, ["class", "style", "id"]);

      var labelChildren = label; // Keep label is original where there should have no colon

      var computedColon = colon === true || contextColon !== false && colon !== false;
      var haveColon = computedColon && !vertical; // Remove duplicated user input colon

      if (haveColon && typeof label === 'string' && label.trim() !== '') {
        labelChildren = label.replace(/[：:]\s*$/, '');
      }

      var labelClassName = classNames((_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-item-required"), required), _defineProperty(_classNames, "".concat(prefixCls, "-item-no-colon"), !computedColon), _classNames));

      var colProps = _objectSpread(_objectSpread({}, restProps), {}, {
        class: labelColClassName,
        key: 'label',
        style: labelColStyle,
        id: labelColId
      });

      return label ? _vue.createVNode(Col, colProps, {
        default: function _default() {
          return [_vue.createVNode("label", {
            "for": htmlFor || fieldId,
            "class": labelClassName,
            "title": typeof label === 'string' ? label : '',
            "onClick": _this4.onLabelClick
          }, [labelChildren])];
        }
      }) : null;
    },
    renderChildren: function renderChildren(prefixCls, child) {
      return [this.renderLabel(prefixCls), this.renderWrapper(prefixCls, this.renderValidateWrapper(prefixCls, child, this.renderHelp(prefixCls), this.renderExtra(prefixCls)))];
    },
    renderFormItem: function renderFormItem(child) {
      var _itemClassName;

      var customizePrefixCls = this.$props.prefixCls;

      var _this$$attrs = this.$attrs,
          className = _this$$attrs.class,
          restProps = _objectWithoutProperties(_this$$attrs, ["class"]);

      var getPrefixCls = this.configProvider.getPrefixCls;
      var prefixCls = getPrefixCls('form', customizePrefixCls);
      var children = this.renderChildren(prefixCls, child);
      var itemClassName = (_itemClassName = {}, _defineProperty(_itemClassName, className, className), _defineProperty(_itemClassName, "".concat(prefixCls, "-item"), true), _defineProperty(_itemClassName, "".concat(prefixCls, "-item-with-help"), this.helpShow), _itemClassName);
      return _vue.createVNode(Row, _vue.mergeProps(restProps, {
        "class": classNames(itemClassName),
        "key": "row"
      }), {
        default: function _default() {
          return [children];
        }
      });
    }
  },
  render: function render() {
    var _this5 = this;

    var _getOptionProps = getOptionProps(this),
        autoLink = _getOptionProps.autoLink;

    var children = getSlot(this);
    var firstChildren = children[0];

    if (this.fieldName && autoLink && isValidElement(firstChildren)) {
      var originalEvents = getEvents(firstChildren);
      var originalBlur = originalEvents.onBlur;
      var originalChange = originalEvents.onChange;
      firstChildren = cloneElement(firstChildren, _objectSpread(_objectSpread({}, this.fieldId ? {
        id: this.fieldId
      } : undefined), {}, {
        onBlur: function onBlur() {
          originalBlur && originalBlur.apply(void 0, arguments);

          _this5.onFieldBlur();
        },
        onChange: function onChange() {
          if (Array.isArray(originalChange)) {
            for (var i = 0, l = originalChange.length; i < l; i++) {
              originalChange[i].apply(originalChange, arguments);
            }
          } else if (originalChange) {
            originalChange.apply(void 0, arguments);
          }

          _this5.onFieldChange();
        }
      }));
    }

    return this.renderFormItem([firstChildren, children.slice(1)]);
  }
};