import { formCollections } from '../internal/form.js'

/**
 * Serializes a form and returns a plain object. If a form control with the same name appears more than once, the
 * property will be converted to an array.
 */
export function serialize(form: HTMLFormElement) {
    const formData = new FormData(form)
    const object: Record<string, unknown> = {}

    formData.forEach((value, key) => {
        if (Reflect.has(object, key)) {
            const entry = object[key]
            if (Array.isArray(entry)) {
                entry.push(value)
            } else {
                object[key] = [object[key], value]
            }
        } else {
            object[key] = value
        }
    })

    return object
}

/**
 * Returns all form controls that are associated with the specified form. Includes both native and Terra form
 * controls. Use this function in lieu of the `HTMLFormElement.elements` property, which doesn't recognize Terra
 * form controls.
 */
export function getFormControls(form: HTMLFormElement) {
    const rootNode = form.getRootNode() as Document | ShadowRoot
    const allNodes = [...rootNode.querySelectorAll('*')]
    const formControls = [...form.elements]
    const collection = formCollections.get(form)
    const TerraFormControls = collection ? Array.from(collection) : []

    // To return form controls in the right order, we sort by DOM index
    return [...formControls, ...TerraFormControls].sort((a: Element, b: Element) => {
        if (allNodes.indexOf(a) < allNodes.indexOf(b)) return -1
        if (allNodes.indexOf(a) > allNodes.indexOf(b)) return 1
        return 0
    })
}
