import { defineComponent, inject, computed, ref, onMounted, onBeforeUnmount, provide, createElementBlock, openBlock, normalizeStyle, normalizeClass, createElementVNode, renderSlot, createTextVNode, toDisplayString, createCommentVNode, unref, Fragment, renderList } from "vue";
import { formItemProps } from "./types.mjs";
import { formInjectKey, formItemInjectKey } from "./provide.mjs";
import { getFlexValue, groupRules } from "./form.mjs";
import { isArray } from "../_utils/is.mjs";
import { moveToFirst, getValueByPath, asyncSome, setValueByPath } from "../_utils/helper.mjs";
import { log } from "../_utils/log.mjs";
const _hoisted_1 = { class: "o-form-item-label" };
const _hoisted_2 = { class: "o-form-item-main" };
const _hoisted_3 = { class: "o-form-item-main-wrap" };
const _hoisted_4 = { key: 0 };
const _hoisted_5 = {
  key: 1,
  class: "o-form-item-extra"
};
const requireSymbol = "*";
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "OFormItem",
  props: formItemProps,
  setup(__props) {
    var _a;
    const props = __props;
    const formInject = inject(formInjectKey, {});
    const align = computed(() => getFlexValue(props.labelAlign));
    const justify = computed(() => getFlexValue(props.labelJustify));
    const isRequired = computed(() => {
      if (props.required) {
        return true;
      } else if (isArray(props.rules)) {
        return props.rules.some((item) => item.required === true);
      }
      return false;
    });
    const rules = computed(() => groupRules(props.rules, props.required));
    const ruleTriggers = computed(() => {
      const t = Object.keys(rules.value);
      return moveToFirst(t, "change");
    });
    const fieldResult = ref(null);
    const initialVal = ((_a = formInject.model) == null ? void 0 : _a.value) && props.field ? getValueByPath(formInject.model.value, props.field) : void 0;
    const runValidate = async (trigger) => {
      var _a2;
      if (!props.field || !((_a2 = formInject.model) == null ? void 0 : _a2.value)) {
        return null;
      }
      const validators = rules.value[trigger || props.defaultTrigger || ruleTriggers.value[0]];
      if (!validators || validators.length === 0) {
        return null;
      }
      const value = getValueByPath(formInject.model.value, props.field);
      fieldResult.value = null;
      await asyncSome(validators, async (validatorFn) => {
        var _a3;
        try {
          const rlt = await (validatorFn == null ? void 0 : validatorFn(value));
          if ((rlt == null ? void 0 : rlt.type) === "danger") {
            fieldResult.value = {
              type: "danger",
              message: rlt.message ? [rlt.message] : []
            };
            return true;
          } else if ((rlt == null ? void 0 : rlt.type) === "warning") {
            if (!fieldResult.value) {
              fieldResult.value = {
                type: "warning",
                message: rlt.message ? [rlt.message] : []
              };
            } else if (rlt.message) {
              (_a3 = fieldResult.value.message) == null ? void 0 : _a3.push(rlt.message);
            }
            return false;
          }
        } catch (e) {
          log.error("failed to validate rules");
        }
      });
      return fieldResult.value;
    };
    const clearValidate = () => {
      var _a2;
      if (!props.field || !((_a2 = formInject.model) == null ? void 0 : _a2.value)) {
        return;
      }
      fieldResult.value = null;
    };
    const resetFiled = () => {
      var _a2;
      if (((_a2 = formInject.model) == null ? void 0 : _a2.value) && props.field) {
        setValueByPath(formInject.model.value, props.field, initialVal);
      }
    };
    const fieldHandlers = {
      runValidate,
      onChange() {
        runValidate("change");
      },
      onFocus() {
        runValidate("focus");
      },
      onInput() {
        runValidate("input");
      },
      onBlur() {
        runValidate("blur");
      }
    };
    onMounted(() => {
      var _a2;
      if (props.field) {
        (_a2 = formInject.addFiled) == null ? void 0 : _a2.call(formInject, {
          filed: props.field,
          validate: runValidate,
          clearValidate,
          resetFiled
        });
      }
    });
    onBeforeUnmount(() => {
      var _a2;
      if (props.field) {
        (_a2 = formInject.removeFiled) == null ? void 0 : _a2.call(formInject, props.field);
      }
    });
    provide(formItemInjectKey, {
      fieldHandlers,
      fieldResult
    });
    return (_ctx, _cache) => {
      var _a2, _b, _c, _d, _e;
      return openBlock(), createElementBlock(
        "div",
        {
          class: normalizeClass(["o-form-item", [
            {
              "o-form-item-required": isRequired.value,
              "o-form-item-danger": ((_a2 = fieldResult.value) == null ? void 0 : _a2.type) === "danger",
              "o-form-item-warning": ((_b = fieldResult.value) == null ? void 0 : _b.type) === "warning"
            }
          ]]),
          style: normalizeStyle({
            "--form-label-width": props.labelWidth,
            "--form-label-align": align.value,
            "--form-label-justify": justify.value
          })
        },
        [
          createElementVNode("div", _hoisted_1, [
            createElementVNode(
              "span",
              {
                class: normalizeClass(["o-form-require-symbol", {
                  visible: isRequired.value
                }])
              },
              [
                renderSlot(_ctx.$slots, "symbol", {}, () => [
                  createTextVNode(toDisplayString(requireSymbol))
                ])
              ],
              2
              /* CLASS */
            ),
            renderSlot(_ctx.$slots, "label", {}, () => [
              createElementVNode(
                "span",
                null,
                toDisplayString(props.label),
                1
                /* TEXT */
              )
            ])
          ]),
          createElementVNode("div", _hoisted_2, [
            createElementVNode("div", _hoisted_3, [
              renderSlot(_ctx.$slots, "default")
            ]),
            ((_c = fieldResult.value) == null ? void 0 : _c.message) ? (openBlock(), createElementBlock(
              "div",
              {
                key: 0,
                class: normalizeClass(["o-form-item-message", `type-${fieldResult.value.type}`])
              },
              [
                renderSlot(_ctx.$slots, "message", {
                  message: (_d = fieldResult.value) == null ? void 0 : _d.message,
                  type: (_e = fieldResult.value) == null ? void 0 : _e.type
                }, () => {
                  var _a3, _b2, _c2;
                  return [
                    !unref(isArray)((_a3 = fieldResult.value) == null ? void 0 : _a3.message) ? (openBlock(), createElementBlock(
                      "div",
                      _hoisted_4,
                      toDisplayString((_b2 = fieldResult.value) == null ? void 0 : _b2.message),
                      1
                      /* TEXT */
                    )) : (openBlock(true), createElementBlock(
                      Fragment,
                      { key: 1 },
                      renderList((_c2 = fieldResult.value) == null ? void 0 : _c2.message, (item) => {
                        return openBlock(), createElementBlock(
                          "div",
                          { key: item },
                          toDisplayString(item),
                          1
                          /* TEXT */
                        );
                      }),
                      128
                      /* KEYED_FRAGMENT */
                    ))
                  ];
                })
              ],
              2
              /* CLASS */
            )) : createCommentVNode("v-if", true),
            _ctx.$slots.extra ? (openBlock(), createElementBlock("div", _hoisted_5, [
              renderSlot(_ctx.$slots, "extra")
            ])) : createCommentVNode("v-if", true)
          ])
        ],
        6
        /* CLASS, STYLE */
      );
    };
  }
});
export {
  _sfc_main as default
};
