---
import type { HTTPSubmitMethod, Submit } from '@astro-reactive/common';
import { FormGroup, FormControl } from '../core';
import FieldSet from './FieldSet.astro';
import Field from './Field.astro';
import ShortUniqueId from 'short-unique-id';

export interface Props {
	/**
	 * Determines how the form is rendered
	 */
	formGroups: FormGroup | FormGroup[];

	/**
	 * Sets the `action` attribute for the form. Set this to the URL that processes the form submission.
	 * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method
	 */
	action?: string;

	/**
	 * Sets the `method` attribute for the form. Set this to the HTTP method to submit the form: 'post', 'get', or 'dialog'.
	 * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method
	 */
	method?: HTTPSubmitMethod;

	/**
	 * Sets the whole form as read-only.
	 */
	readOnly?: boolean;

	/**
	 * When used with our `validator` package, the `Form` component is able to render validation hints when `showValidationHints` is set to true:
	 * - asterisks on required controls' labels
	 * - controls with validation errors are colored red
	 */
	showValidationHints?: boolean;

	/**
	 * A special button that triggers the submit event for a form.
	 */
	submitControl?: Submit;

	/**
	 * Sets the form to use light or dark mode.
	 */
	theme?: 'light' | 'dark';

	/**
	 * When used with our `validator` package, the `Form` component is able to render validation errors on server-side rendering when `validateOnLoad` is set to true. Otherwise, the validation errors will only be rendered on the client-side upon user interaction.
	 */
	validateOnLoad?: boolean;
}

const {
	submitControl,
	formGroups = [],
	theme,
	showValidationHints = false,
	validateOnLoad = true,
	readOnly = false,
	action = '',
	method = 'get',
} = Astro.props;

const uid = new ShortUniqueId({ length: 9 });
const formTheme = theme ?? 'light';
const formName = Array.isArray(formGroups) ? null : formGroups?.name || null;
const formId = Array.isArray(formGroups) ? uid() : formGroups?.id || null;

// if `validateOnLoad` prop is true,
// it should forced all FormControl to validate on load
if (validateOnLoad) {
	if (Array.isArray(formGroups)) {
		formGroups.forEach((group) =>
			group.controls.forEach((control) => {
				if ('setValidateOnLoad' in control) {
					control.setValidateOnLoad(validateOnLoad);
				}
			})
		);
	} else {
		formGroups.controls.forEach((control) => {
			if ('setValidateOnLoad' in control) {
				control.setValidateOnLoad(validateOnLoad);
			}
		});
	}
}
---

<form
	class={formTheme}
	name={formName}
	id={formId}
	data-validator-hints={showValidationHints.toString()}
	action={action}
	method={method}
>
	{
		Array.isArray(formGroups)
			? formGroups?.map((group) => (
					<FieldSet showValidationHints={showValidationHints} group={group} readOnly={readOnly} />
			  ))
			: formGroups?.controls.map((control) => (
					<Field showValidationHints={showValidationHints} control={control} readOnly={readOnly} />
			  ))
	}
	{
		submitControl && (
			<Field showValidationHints={showValidationHints} control={new FormControl(submitControl)} />
		)
	}
</form>

<style>
	.light {
		color-scheme: light;
	}

	.dark {
		color-scheme: dark;
	}
</style>

<style is:global>
	[data-validator-hints='true'][data-validator-error='true'],
	[data-validator-hints='true'] [data-validator-error='true'] {
		color: red;
		border-color: red;
	}
	[data-validator-hints='true'][data-validator-warn='true'],
	[data-validator-hints='true'] [data-validator-warn='true'] {
		color: orange;
		border-color: orange;
	}
	[data-validator-hints='true'][data-validator-info='true'],
	[data-validator-hints='true'] [data-validator-info='true'] {
		color: green;
		border-color: green;
	}
</style>
