import isArray from "lodash/isArray";
import isEqual from "lodash/isEqual";
import mergeWith from "lodash/mergeWith";

/**
 * Recursively merges two objects into the new object
 *
 * @param object1 The first object.
 * @param object2 The second object.
 */
const mergeToNew = <TObject1, TObject2>(object1: TObject1, object2: TObject2): TObject1 & TObject2 => {
    return mergeWith({}, object1, object2, (object: any, source: any, key: string) => {
        if (isCssCustomizer(object, key) && isArray(object)) {
            return object.concat(source);
        }
    });
};

let cachedObjectWithCssOverrides: any;

const isCssCustomizer = (object: any, key: any) => {
    if (typeof key !== "string") {
        return false;
    }

    if (key === "cssOverrides") {
        cachedObjectWithCssOverrides = object;
        return false;
    }

    if (key.toLowerCase().endsWith("css")) {
        return true;
    }

    const cachedProp = cachedObjectWithCssOverrides?.[key];
    if (cachedProp && isEqual(cachedProp, object)) {
        return true;
    }

    return false;
};

export default mergeToNew;
