/*
 * Copyright 2020 Adobe. All rights reserved.
 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
 * OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
import clsx from 'clsx';
/**
 * Calls all functions in the order they were chained with the same arguments.
 * @internal
 */
export function chain(...callbacks) {
    return (...args) => {
        for (const callback of callbacks) {
            if (typeof callback === 'function') {
                try {
                    callback(...args);
                }
                catch (e) {
                    console.error(e);
                }
            }
        }
    };
}
/**
 * Merges multiple props objects together. Event handlers are chained,
 * classNames are combined, and ids are deduplicated - different ids
 * will trigger a side-effect and re-render components hooked up with `useId`.
 * For all other props, the last prop object overrides all previous ones.
 * @param args - Multiple sets of props to merge together.
 * @internal
 */
export function mergePropsReactAria(...args) {
    // Start with a base clone of the first argument. This is a lot faster than starting
    // with an empty object and adding properties as we go.
    const result = Object.assign({}, args[0]);
    for (let i = 1; i < args.length; i++) {
        const props = args[i];
        for (const key in props) {
            const a = result[key];
            const b = props[key];
            // Chain events
            if (typeof a === 'function' &&
                typeof b === 'function' &&
                // This is a lot faster than a regex.
                key[0] === 'o' &&
                key[1] === 'n' &&
                key.charCodeAt(2) >= /* 'A' */ 65 &&
                key.charCodeAt(2) <= /* 'Z' */ 90) {
                result[key] = chain(a, b);
                // Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check
            }
            else if ((key === 'className' || key === 'UNSAFE_className') && typeof a === 'string' && typeof b === 'string') {
                result[key] = clsx(a, b);
            }
            else {
                result[key] = b !== undefined ? b : a;
            }
        }
    }
    return result;
}
export function isProp(prop) {
    return prop !== undefined;
}
export function mergeProps(...props) {
    return mergePropsReactAria(...props.filter(isProp));
}
