import cloneDeepWith from 'lodash/cloneDeepWith';
import isPlainObject from 'lodash/isPlainObject';
import { createUuid } from '../../AdaptableState/Uuid';
import packageJson from '../../../package.json';
const GET_CURRENT_VERSION = () => {
    const globalObject = typeof globalThis !== 'undefined' ? globalThis : window;
    return ((typeof globalObject['GET_CURRENT_ADAPTABLE_VERSION'] === 'function'
        ? globalObject['GET_CURRENT_ADAPTABLE_VERSION']()
        : packageJson.version) ?? packageJson.version);
};
export function addUuidsToInitialState(initialState) {
    const customizer = (value) => {
        // so whenever we clone a plain object,
        // we add a Uuid property
        // jw added 9/8/20: unless there is on there already
        if (isPlainObject(value) && value != initialState) {
            if (value.Uuid == null || value.Uuid == undefined) {
                value.Uuid = createUuid();
            }
            if (value.AdaptableVersion == null) {
                value.AdaptableVersion = GET_CURRENT_VERSION();
            }
        }
    };
    return cloneDeepWith(initialState, customizer);
}
export function getAccessLevelForObject(adaptableObject, moduleAccessLevel) {
    // we always return the Module Access Level unless the following condition is met:
    // the object prpoerty has been set and set to true and the Module entitlement is full
    if (moduleAccessLevel == 'Full' &&
        adaptableObject &&
        adaptableObject.IsReadOnly &&
        adaptableObject.IsReadOnly == true) {
        return 'ReadOnly';
    }
    return moduleAccessLevel;
}
export function addAdaptableObjectPrimitives(adaptableObject) {
    if (!adaptableObject.Uuid) {
        adaptableObject.Uuid = createUuid();
    }
    adaptableObject.Source = 'User';
    adaptableObject.AdaptableVersion = GET_CURRENT_VERSION();
    return adaptableObject;
}
export function removeAdaptableObjectPrimitivesInline(target) {
    if (!target || typeof target !== 'object') {
        return target;
    }
    delete target.Source;
    delete target.Uuid;
    delete target.AdaptableVersion;
    return target;
}
export function removeAdaptableObjectPrimitives(adaptableObject) {
    const clonedObject = structuredClone(adaptableObject);
    const sanitiseObject = (object) => {
        for (const key in object) {
            if (key === 'Source' || key === 'Uuid' || key === 'AdaptableVersion') {
                delete object[key];
            }
            else if (Array.isArray(object[key])) {
                object[key].forEach((item) => sanitiseObject(item));
            }
            else if (typeof object[key] === 'object') {
                sanitiseObject(object[key]);
            }
        }
    };
    sanitiseObject(clonedObject);
    return clonedObject;
}
// pretty primitive type guard for AdaptableObject, but currently there is no better/safer way
export function isAdaptableObject(object) {
    return object != undefined && typeof object['Uuid'] === 'string';
}
export const AdaptableHelper = {
    addUuidsToInitialState: addUuidsToInitialState,
    getAccessLevelForObject,
    addAdaptableObjectPrimitives,
    removeAdaptableObjectPrimitives,
    removeAdaptableObjectPrimitivesInline,
    isAdaptableObject,
};
export default AdaptableHelper;
