import get from 'lodash/get';
import isObject from './isObject';
/** Merges the `defaults` object of type `T` into the `formData` of type `T`
 *
 * When merging defaults and form data, we want to merge in this specific way:
 * - objects are deeply merged
 * - arrays are merged in such a way that:
 *   - when the array is set in form data, only array entries set in form data
 *     are deeply merged; additional entries from the defaults are ignored unless `mergeExtraArrayDefaults` is true, in
 *     which case the extras are appended onto the end of the form data
 *   - when the array is not set in form data, the default is copied over
 * - scalars are overwritten/set by form data unless undefined and there is a default AND `defaultSupercedesUndefined`
 *   is true
 *
 * @param [defaults] - The defaults to merge
 * @param [formData] - The form data into which the defaults will be merged
 * @param [mergeExtraArrayDefaults=false] - If true, any additional default array entries are appended onto the formData
 * @param [defaultSupercedesUndefined=false] - If true, an explicit undefined value will be overwritten by the default value
 * @returns - The resulting merged form data with defaults
 */
export default function mergeDefaultsWithFormData(defaults, formData, mergeExtraArrayDefaults = false, defaultSupercedesUndefined = false) {
    if (Array.isArray(formData)) {
        const defaultsArray = Array.isArray(defaults) ? defaults : [];
        const mapped = formData.map((value, idx) => {
            if (defaultsArray[idx]) {
                return mergeDefaultsWithFormData(defaultsArray[idx], value, mergeExtraArrayDefaults, defaultSupercedesUndefined);
            }
            return value;
        });
        // Merge any extra defaults when mergeExtraArrayDefaults is true
        if (mergeExtraArrayDefaults && mapped.length < defaultsArray.length) {
            mapped.push(...defaultsArray.slice(mapped.length));
        }
        return mapped;
    }
    if (isObject(formData)) {
        const acc = Object.assign({}, defaults); // Prevent mutation of source object.
        return Object.keys(formData).reduce((acc, key) => {
            acc[key] = mergeDefaultsWithFormData(defaults ? get(defaults, key) : {}, get(formData, key), mergeExtraArrayDefaults, defaultSupercedesUndefined);
            return acc;
        }, acc);
    }
    if (defaultSupercedesUndefined && formData === undefined) {
        return defaults;
    }
    return formData;
}
//# sourceMappingURL=mergeDefaultsWithFormData.js.map