<template>
  <view :class="formClass" :style="formStyle">
    <slot></slot>
  </view>
</template>

<script lang="ts">
import { defineComponent as _defineComponent } from "vue";
import { computed, reactive, provide, toRef, watch, markRaw } from "vue";
import {
  classNames,
  stringifyStyle,
  createBem,
  toArray,
  arrayEqual,
  noop
} from "../utils";
import {
  formContextSymbol,
  formProps
} from "./common";
import { Validator } from "./Validator";
import { useTranslate } from "../locale";
const __default__ = {
  options: {
    virtualHost: true,
    styleIsolation: "shared"
  }
};
export default /* @__PURE__ */ _defineComponent({
  ...__default__,
  __name: "form",
  props: formProps,
  setup(__props, { expose: __expose }) {
    const props = __props;
    const bem = createBem("form");
    const getMatchedField = (name) => {
      return fields.find((field) => {
        return arrayEqual(toArray(field.name), toArray(name));
      });
    };
    const getMatchedFields = (nameList) => {
      let matchedFields = fields;
      if (nameList && nameList.length > 0) {
        matchedFields = fields.filter((field) => {
          return nameList.findIndex(
            (name) => arrayEqual(toArray(field.name), toArray(name))
          ) > -1;
        });
      }
      return matchedFields;
    };
    const validate = async (nameList) => {
      const settledResult = await Promise.allSettled(
        getMatchedFields(nameList).map((field) => {
          return field.validate();
        })
      );
      const rejectedResult = settledResult.filter((result) => {
        return result.status === "rejected";
      });
      if (rejectedResult.length > 0) {
        const errors = rejectedResult.map((result) => {
          return result.reason;
        });
        if (props.scrollToFirstError) {
          scrollToField(errors[0].name);
        }
        throw errors;
      }
    };
    const reset = async (nameList) => {
      await Promise.allSettled(
        getMatchedFields(nameList).map((field) => {
          field.reset();
        })
      );
    };
    const clearValidate = async (nameList) => {
      await Promise.allSettled(
        getMatchedFields(nameList).map((field) => {
          field.clearValidate();
        })
      );
    };
    const scrollToField = (name) => {
      getMatchedField(name)?.scrollToField();
    };
    __expose({
      validate,
      reset,
      clearValidate,
      scrollToField
    });
    const fields = [];
    const addField = (formItemContext) => {
      fields.push(formItemContext);
    };
    const removeField = (formItemContext) => {
      fields.splice(fields.indexOf(formItemContext), 1);
    };
    const validator = markRaw(new Validator());
    const { select } = useTranslate("form.defaultValidateMessages");
    validator.setValidateMessages(select());
    watch(
      () => props.rules,
      () => {
        if (props.validateOnRuleChange) {
          validate().catch(noop);
        }
      },
      {
        deep: true
      }
    );
    provide(
      formContextSymbol,
      reactive({
        model: toRef(props, "model"),
        rules: toRef(props, "rules"),
        validateTrigger: toRef(props, "validateTrigger"),
        direction: toRef(props, "direction"),
        labelWidth: toRef(props, "labelWidth"),
        labelAlign: toRef(props, "labelAlign"),
        labelValign: toRef(props, "labelValign"),
        starPosition: toRef(props, "starPosition"),
        showError: toRef(props, "showError"),
        scrollIntoViewOptions: toRef(props, "scrollIntoViewOptions"),
        disabled: toRef(props, "disabled"),
        readonly: toRef(props, "readonly"),
        addField,
        removeField,
        validator
      })
    );
    const formClass = computed(() => {
      return classNames(bem.b(), props.rootClass);
    });
    const formStyle = computed(() => {
      return stringifyStyle(props.rootStyle);
    });
    const __returned__ = { props, bem, getMatchedField, getMatchedFields, validate, reset, clearValidate, scrollToField, fields, addField, removeField, validator, select, formClass, formStyle };
    return __returned__;
  }
});
</script>

<style lang="scss">
@use './index.scss';
</style>