import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';

/**
 * Cleanup `undefined` from the result.
 * To minimize conflicts when merging with user defined props
 */
function simplify(props) {
  for (var key in props) {
    if (props[key] === undefined) {
      delete props[key];
    }
  }
  return props;
}

/**
 * Derives aria attributes of a form control based on the field metadata.
 */
function getAriaAttributes(metadata) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  if (typeof options.ariaAttributes !== 'undefined' && !options.ariaAttributes) {
    return {};
  }
  var invalid = options.ariaInvalid === 'allErrors' ? !metadata.valid : typeof metadata.errors !== 'undefined';
  var ariaDescribedBy = options.ariaDescribedBy;
  return simplify({
    'aria-invalid': invalid || undefined,
    'aria-describedby': invalid ? "".concat(metadata.errorId, " ").concat(ariaDescribedBy !== null && ariaDescribedBy !== void 0 ? ariaDescribedBy : '').trim() : ariaDescribedBy
  });
}

/**
 * Derives the properties of a form element based on the form metadata,
 * including `id`, `onSubmit`, `noValidate`, `aria-invalid` and `aria-describedby`.
 *
 * @example
 * ```tsx
 * <form {...getFormProps(metadata)} />
 * ```
 */
function getFormProps(metadata, options) {
  return simplify(_objectSpread2({
    id: metadata.id,
    onSubmit: metadata.onSubmit,
    noValidate: metadata.noValidate
  }, getAriaAttributes(metadata, options)));
}

/**
 * Derives the properties of a fieldset element based on the field metadata,
 * including `id`, `name`, `form`, `aria-invalid` and `aria-describedby`.
 *
 * @example
 * ```tsx
 * <fieldset {...getFieldsetProps(metadata)} />
 * ```
 */
function getFieldsetProps(metadata, options) {
  return simplify(_objectSpread2({
    id: metadata.id,
    name: metadata.name,
    form: metadata.formId
  }, getAriaAttributes(metadata, options)));
}

/**
 * Derives common properties of a form control based on the field metadata,
 * including `key`, `id`, `name`, `form`, `required`, `autoFocus`, `aria-invalid` and `aria-describedby`.
 */
function getFormControlProps(metadata, options) {
  return simplify(_objectSpread2({
    key: metadata.key,
    required: metadata.required || undefined
  }, getFieldsetProps(metadata, options)));
}

/**
 * Derives the properties of an input element based on the field metadata,
 * including common form control attributes like `key`, `id`, `name`, `form`, `autoFocus`, `aria-invalid`, `aria-describedby`
 * and constraint attributes such as `type`, `required`, `minLength`, `maxLength`, `min`, `max`, `step`, `pattern`, `multiple`.
 * Depends on the provided options, it will also set `defaultChecked` / `checked` if it is a checkbox or radio button,
 * or otherwise `defaultValue` / `value`.
 *
 * @see https://conform.guide/api/react/getInputProps
 * @example
 * ```tsx
 * // To setup an uncontrolled input
 * <input {...getInputProps(metadata, { type: 'text' })} />
 * // To setup an uncontrolled checkbox
 * <input {...getInputProps(metadata, { type: 'checkbox' })} />
 * // To setup an input without defaultValue
 * <input {...getInputProps(metadata, { value: false })} />
 * // To setup a radio button without defaultChecked state
 * <input {...getInputProps(metadata, { type: 'radio', value: false })} />
 * ```
 */
function getInputProps(metadata, options) {
  var props = _objectSpread2(_objectSpread2({}, getFormControlProps(metadata, options)), {}, {
    type: options.type,
    minLength: metadata.minLength,
    maxLength: metadata.maxLength,
    min: metadata.min,
    max: metadata.max,
    step: metadata.step,
    pattern: metadata.pattern,
    multiple: metadata.multiple
  });
  if (typeof options.value === 'undefined' || options.value) {
    if (options.type === 'checkbox' || options.type === 'radio') {
      props.value = typeof options.value === 'string' ? options.value : 'on';
      props.defaultChecked = typeof metadata.initialValue === 'boolean' ? metadata.initialValue : metadata.initialValue === props.value;
    } else if (typeof metadata.initialValue === 'string') {
      props.defaultValue = metadata.initialValue;
    }
  }
  return simplify(props);
}

/**
 * Derives the properties of a select element based on the field metadata,
 * including common form control attributes like `key`, `id`, `name`, `form`, `autoFocus`, `aria-invalid`, `aria-describedby`
 * and constraint attributes such as `required` or `multiple`.
 * Depends on the provided options, it will also set `defaultValue` / `value`.
 *
 * @see https://conform.guide/api/react/getSelectProps
 * @example
 * ```tsx
 * // To setup an uncontrolled select
 * <select {...getSelectProps(metadata)} />
 * // To setup a select without defaultValue
 * <select {...getSelectProps(metadata, { value: false })} />
 * ```
 */
function getSelectProps(metadata) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var props = _objectSpread2(_objectSpread2({}, getFormControlProps(metadata, options)), {}, {
    multiple: metadata.multiple
  });
  if (typeof options.value === 'undefined' || options.value) {
    var _metadata$initialValu;
    props.defaultValue = Array.isArray(metadata.initialValue) ? metadata.initialValue.map(item => "".concat(item !== null && item !== void 0 ? item : '')) : (_metadata$initialValu = metadata.initialValue) === null || _metadata$initialValu === void 0 ? void 0 : _metadata$initialValu.toString();
  }
  return simplify(props);
}

/**
 * Derives the properties of a textarea element based on the field metadata,
 * including common form control attributes like `key`, `id`, `name`, `form`, `autoFocus`, `aria-invalid`, `aria-describedby`
 * and constraint attributes such as `required`, `minLength` or `maxLength`.
 * Depends on the provided options, it will also set `defaultValue` / `value`.
 *
 * @see https://conform.guide/api/react/getTextareaProps
 * @example
 * ```tsx
 * // To setup an uncontrolled textarea
 * <textarea {...getTextareaProps(metadata)} />
 * // To setup a textarea without defaultValue
 * <textarea {...getTextareaProps(metadata, { value: false })} />
 * ```
 */
function getTextareaProps(metadata) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var props = _objectSpread2(_objectSpread2({}, getFormControlProps(metadata, options)), {}, {
    minLength: metadata.minLength,
    maxLength: metadata.maxLength
  });
  if (typeof options.value === 'undefined' || options.value) {
    var _metadata$initialValu2;
    props.defaultValue = (_metadata$initialValu2 = metadata.initialValue) === null || _metadata$initialValu2 === void 0 ? void 0 : _metadata$initialValu2.toString();
  }
  return simplify(props);
}

/**
 * Derives the properties of a collection of checkboxes or radio buttons based on the field metadata,
 * including common form control attributes like `key`, `id`, `name`, `form`, `autoFocus`, `aria-invalid`, `aria-describedby` and `required`.
 *
 * @see https://conform.guide/api/react/getTextareaProps
 * @example
 * ```tsx
 * <fieldset>
 *   {getCollectionProps(metadata, {
 *     type: 'checkbox',
 *     options: ['a', 'b', 'c']
 *   }).map((props) => (
 *     <div key={props.key}>
 *       <label htmlFor={props.id}>{props.value}</label>
 *       <input {...props} />
 *     </div>
 *  ))}
 * </fieldset>
 * ```
 */
function getCollectionProps(metadata, options) {
  return options.options.map(value => {
    var _metadata$key;
    return simplify(_objectSpread2(_objectSpread2({}, getFormControlProps(metadata, options)), {}, {
      key: "".concat((_metadata$key = metadata.key) !== null && _metadata$key !== void 0 ? _metadata$key : '').concat(value),
      id: "".concat(metadata.id, "-").concat(value),
      type: options.type,
      value,
      defaultChecked: typeof options.value === 'undefined' || options.value ? options.type === 'checkbox' && Array.isArray(metadata.initialValue) ? metadata.initialValue.includes(value) : metadata.initialValue === value : undefined,
      // The required attribute doesn't make sense for checkbox group
      // As it would require all checkboxes to be checked instead of at least one
      // It is overriden with `undefiend` so it could be cleaned up properly
      required: options.type === 'checkbox' ? undefined : metadata.required
    }));
  });
}

export { getAriaAttributes, getCollectionProps, getFieldsetProps, getFormControlProps, getFormProps, getInputProps, getSelectProps, getTextareaProps };
