import { IPrimitive } from "../types";
/**
 * Determines whether a value is a plain object (POJO - Plain Old JavaScript Object).
 *
 * A plain object is an object created by the Object constructor or one with a null prototype.
 * This function performs comprehensive checks to distinguish plain objects from other object types
 * like arrays, dates, DOM elements, regular expressions, class instances, and functions.
 * It also handles cross-frame compatibility where objects might be created in different execution contexts.
 *
 * @template T - The type of the value being checked
 * @param {T} obj - The value to test for being a plain object
 *
 * @returns {obj is (T extends (Record<any, any> | object) ? T : T extends string | undefined | null | boolean | Array<any> ? never : any)}
 * Type predicate that narrows the type to a plain object if the check passes, or never for non-object types
 *
 * @example
 * ```typescript
 * // Basic plain object detection
 * const plainObj = { name: "John", age: 30 };
 * console.log(isObj(plainObj)); // true
 *
 * // Object created with Object.create(null)
 * const nullProtoObj = Object.create(null);
 * nullProtoObj.prop = "value";
 * console.log(isObj(nullProtoObj)); // true
 *
 * // Arrays are not plain objects
 * const array = [1, 2, 3];
 * console.log(isObj(array)); // false
 *
 * // Dates are not plain objects
 * const date = new Date();
 * console.log(isObj(date)); // false
 *
 * // Regular expressions are not plain objects
 * const regex = /pattern/;
 * console.log(isObj(regex)); // false
 *
 * // Class instances are not plain objects
 * class MyClass {
 *   constructor(public value: string) {}
 * }
 * const instance = new MyClass("test");
 * console.log(isObj(instance)); // false
 *
 * // Functions are not plain objects
 * const func = () => {};
 * console.log(isObj(func)); // false
 *
 * // Primitives are not plain objects
 * console.log(isObj("string")); // false
 * console.log(isObj(42)); // false
 * console.log(isObj(true)); // false
 * console.log(isObj(null)); // false
 * console.log(isObj(undefined)); // false
 *
 * // DOM elements are not plain objects (in browser environment)
 * const element = document.createElement('div');
 * console.log(isObj(element)); // false
 * ```
 *
 * @example
 * ```typescript
 * // Type narrowing with TypeScript
 * function processValue<T>(value: T): void {
 *   if (isObj(value)) {
 *     // TypeScript now knows 'value' is a plain object
 *     // Safe to access object properties
 *     Object.keys(value).forEach(key => {
 *       console.log(`${key}: ${value[key]}`);
 *     });
 *   } else {
 *     // Handle non-object values
 *     console.log("Not a plain object:", value);
 *   }
 * }
 *
 * // Cross-frame compatibility example
 * // Works even when objects are created in different iframes
 * const iframe = document.createElement('iframe');
 * document.body.appendChild(iframe);
 * const iframeWindow = iframe.contentWindow;
 * const crossFrameObj = new iframeWindow.Object();
 * crossFrameObj.prop = "value";
 * console.log(isObj(crossFrameObj)); // true (handles cross-frame objects)
 * ```
 *
 * @remarks
 * This function is particularly useful for:
 * - Object serialization/deserialization logic
 * - Deep cloning or merging operations where you need to distinguish plain objects
 * - API response validation where you expect plain data objects
 * - Library functions that need to handle various object types differently
 * - Cross-frame scenarios in browser environments
 *
 * The function performs several layers of validation:
 * 1. **Early rejection**: Filters out null, primitives, arrays, dates, regex, and DOM elements
 * 2. **Null prototype check**: Accepts objects created with `Object.create(null)`
 * 3. **Constructor validation**: Verifies the object's constructor is a function
 * 4. **Standard Object check**: Accepts objects with `Object` as constructor
 * 5. **Prototype chain validation**: Ensures the prototype chain is standard
 * 6. **Cross-frame compatibility**: Handles objects from different execution contexts
 *
 * @since 1.0.0
 * @category Type Guards
 * @see {@link cloneObject} - For cloning plain objects
 * @see {@link extendObj} - For merging plain objects
 * @see {@link defaultObj} - For providing default plain objects
 */
export declare function isObj<T = any>(obj: T): obj is T extends Record<any, any> | object ? T : T extends string | undefined | null | boolean | Array<any> ? never : any;
/**
 * Clones a source object by returning a non-reference copy of the object.
 *
 * This function creates a deep copy of the provided object.
 * Any nested objects or arrays within the source will also be cloned, ensuring that the
 * returned object does not reference the original object.
 *
 * @template T - The type of the object to clone. This can be any type, including arrays and nested objects.
 * @param {T} source - The object to clone. This can be any type, including arrays and nested objects.
 *
 * @returns {T} A deep cloned copy of the source object. The return type can be
 * either an object or an array, depending on the input.
 *
 * @example
 * ```ts
 * // Example with a simple object
 * const original = { a: 1, b: { c: 2 } };
 * const cloned = cloneObject(original);
 * console.log(cloned); // Outputs: { a: 1, b: { c: 2 } }
 *
 * // Modifying the cloned object does not affect the original
 * cloned.b.c = 3;
 * console.log(original.b.c); // Outputs: 2 (original remains unchanged)
 *
 * // Example with an array
 * const originalArray = [1, 2, { a: 3 }];
 * const clonedArray = cloneObject(originalArray);
 * console.log(clonedArray); // Outputs: [1, 2, { a: 3 }]
 *
 * // Modifying the cloned array does not affect the original
 * clonedArray[2].a = 4;
 * console.log(originalArray[2].a); // Outputs: 3 (original remains unchanged)
 *
 * // Example with a nested structure
 * const complexObject = { a: 1, b: [2, { c: 3 }] };
 * const clonedComplex = cloneObject(complexObject);
 * console.log(clonedComplex); // Outputs: { a: 1, b: [2, { c: 3 }] }
 * ```
 */
export declare function cloneObject<T = any>(source: T): T;
/**
 * Calculates the size of an object or array.
 *
 * This function returns the number of own properties of an object or the length of an array.
 * If the input is null or not an object, it returns 0.
 *
 * @param {any} obj - The object or array whose size is to be calculated.
 * @param {boolean} [breakOnFirstElementFound=false] - Optional flag to determine if the function should
 * return the size immediately upon finding the first property or element.
 *
 * @returns {number} The size of the object or array. Returns 0 if the input is null or not an object.
 *
 * @example
 * // Example with an object
 * const exampleObject = { a: 1, b: 2, c: 3 };
 * const size = objectSize(exampleObject);
 * console.log(size); // Outputs: 3
 *
 * @example
 * // Example with an array
 * const exampleArray = [1, 2, 3, 4];
 * const arraySize = objectSize(exampleArray);
 * console.log(arraySize); // Outputs: 4
 *
 * @example
 * // Example with breakOnFirstElementFound
 * const earlyExitSize = objectSize(exampleObject, true);
 * console.log(earlyExitSize); // Outputs: 1, as it returns after the first property
 *
 * @example
 * // Example with a null input
 * const nullSize = objectSize(null);
 * console.log(nullSize); // Outputs: 0
 *
 * @example
 * // Example with a non-object input
 * const nonObjectSize = objectSize(42);
 * console.log(nonObjectSize); // Outputs: 0
 */
export declare const objectSize: (obj: any, breakOnFirstElementFound?: boolean) => number;
/**
 * Returns a default object based on the provided arguments.
 *
 * This function takes multiple arguments and returns the first non-empty object found.
 * If only one argument is provided, it returns that argument if it is an object; otherwise, it returns an empty object.
 * If no valid object is found among the arguments, it returns an empty object.
 *
 * @param {...any[]} args - The arguments to check for objects.
 * @template T - The type of the object to return.
 *
 * @returns {object} The first non-empty object found among the arguments, or an empty object if none is found.
 *
 * @example
 * ```ts
 * // Example with one valid object
 * const result1 = defaultObj({ a: 1 });
 * console.log(result1); // Outputs: { a: 1 }
 *
 * // Example with one invalid argument
 * const result2 = defaultObj("not an object");
 * console.log(result2); // Outputs: {}
 *
 * // Example with multiple arguments, returning the first non-empty object
 * const result3 = defaultObj({}, { b: 2 }, { c: 3 });
 * console.log(result3); // Outputs: { b: 2 }
 *
 * // Example with multiple arguments, returning the last valid object
 * const result4 = defaultObj({}, {}, { d: 4 });
 * console.log(result4); // Outputs: { d: 4 }
 *
 * // Example with no valid objects
 * const result5 = defaultObj(null, undefined, "string");
 * console.log(result5); // Outputs: {}
 * ```
 */
export declare function defaultObj<T extends object = any>(...args: any[]): T;
/**
 * Declares a global interface extension for the built-in `Object` type.
 */
declare global {
    /**
     * Interface extension for the built-in `Object` type.
     */
    interface Object {
        /**
         * Clones a source object by returning a non-reference copy of the object.
         *
         * This method creates a deep clone of the provided object, ensuring that nested objects
         * are also cloned, and modifications to the cloned object do not affect the original.
         *
         * @param {any} obj - The object to clone. This can be any type, including arrays and nested objects.
         * @returns {any} The cloned object, which can be an object or an array.
         *
         * @example
         * ```ts
         * const original = { a: 1, b: { c: 2 } };
         * const cloned = Object.clone(original);
         * console.log(cloned); // Outputs: { a: 1, b: { c: 2 } }
         *
         * cloned.b.c = 3;
         * console.log(original.b.c); // Outputs: 2 (original remains unchanged)
         * ```
         * @template T - The type of the object to clone.
         * @param {T} obj - The object to clone.
         * @returns {T} A clone of the object.
         */
        clone: <T = any>(obj: T) => T;
        /**
         * Determines the size of an object or array.
         *
         * This method calculates the number of own enumerable properties in an object or
         * the number of elements in an array. If the `breakOnFirstElementFound` parameter
         * is set to true, it will return 1 immediately upon finding the first element or property.
         *
         * @param {any} obj - The object or array to determine the size of.
         * @param {boolean} [breakOnFirstElementFound=false] - Whether to return immediately after the first element is found.
         * @returns {number} The size of the object or array. Returns 0 if the input is not an object or array.
         *
         * @example
         * ```ts
         * const obj = { a: 1, b: 2, c: 3 };
         * const size = Object.getSize(obj);
         * console.log(size); // Outputs: 3
         *
         * const arr = [1, 2, 3];
         * const arrSize = Object.getSize(arr);
         * console.log(arrSize); // Outputs: 3
         *
         * const singleElementSize = Object.getSize(arr, true);
         * console.log(singleElementSize); // Outputs: 1 (returns immediately)
         *
         * const emptyObjSize = Object.getSize({});
         * console.log(emptyObjSize); // Outputs: 0
         * ```
         */
        getSize: (obj: any, breakOnFirstElementFound?: boolean) => number;
        /**
         * Flattens a nested object structure into a single-level object with dot/bracket notation keys.
         * Handles various data structures including Arrays, Sets, Maps, and plain objects.
         * Skips non-primitive values like functions, class instances.
         *
         * @param {any} obj - The object to flatten
         * @param {string} [prefix=''] - The prefix to use for nested keys
         * @returns {Record<string, Primitive>} A flattened object with primitive values
         *
         * @example
         * // Basic object flattening
         * _flattenObject({
         *   a: {
         *     b: 'value',
         *     c: 42
         *   }
         * })
         * // Returns: { 'a.b': 'value', 'a.c': 42 }
         *
         * @example
         * // Array handling
         * _flattenObject({
         *   items: ['a', 'b', { nested: 'value' }]
         * })
         * // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' }
         *
         * @example
         * // Map handling
         * _flattenObject({
         *   map: new Map([
         *     ['key1', 'value1'],
         *     ['key2', { nested: 'value2' }]
         *   ])
         * })
         * // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' }
         *
         * @example
         * // Complex nested structure
         * _flattenObject({
         *   array: [1, { a: 2 }],
         *   set: new Set(['x', { b: 'y' }]),
         *   map: new Map([['k', { c: 'v' }]]),
         *   obj: {
         *     deep: {
         *       nested: 'value',
         *       fn: () => {}, // Will be skipped
         *       date: new Date() // Will be skipped
         *     }
         *   }
         * })
         * // Returns: {
         * //   'array[0]': 1,
         * //   'array[1].a': 2,
         * //   'set[0]': 'x',
         * //   'set[1].b': 'y',
         * //   'map[k].c': 'v',
         * //   'obj.deep.nested': 'value'
         * // }
         *
         * @throws {Error} Will not throw errors, but silently skips non-primitive values
         *
         * @category Utilities
         * @since 1.0.0
         */
        flatten(obj: any): Record<string, IPrimitive>;
        /**
         * Enhanced version of Object.entries that preserves key types in TypeScript inference.
         *
         * Unlike the standard Object.entries which types all keys as string, this method
         * maintains the original key types (string | number | symbol) in TypeScript's type system
         * while still following JavaScript's runtime behavior where all keys are strings.
         *
         * @template T - The object type extending Record<string | number, any>
         * @param obj - The object to extract entries from
         * @returns Array of key-value tuples with preserved key types in TypeScript
         *
         * @example
         * ```typescript
         * const obj = { 1: "one", "foo": "bar", 42: "answer" } as const;
         *
         * // Standard Object.entries - all keys typed as string
         * const standard = Object.entries(obj); // [string, string][]
         *
         * // Enhanced Object.typedEntries - preserves original key types
         * const typed = Object.typedEntries(obj);
         * // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[]
         * ```
         *
         * @remarks
         * - Runtime behavior is identical to Object.entries (all keys are strings)
         * - Only TypeScript inference is enhanced to remember original key types
         * - Works best with objects declared with 'as const' for literal type inference
         * - Particularly useful for objects with mixed string and numeric keys
         *
         * @since 1.0.0
         */
        typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{
            [K in keyof T]: [K, T[K]];
        }[keyof T]>;
    }
}
/**
 * Extends an object by merging properties from one or more source objects.
 *
 * This function takes a target object and one or more source objects, merging the properties
 * from the source objects into the target object. If a property exists in both the target
 * and a source object, the value from the source object will overwrite the target's value.
 * For arrays, the function merges the contents of the arrays, preserving the original order of the elements.
 *@template T - The type of the target object.
 * @param {T} target - The object to extend. It will receive the new properties.
 * @param {...any[]} sources - The source objects to merge into the target. These objects will not be modified.
 * @returns {T} The extended target object, which contains properties from the source objects.
 *
 * @example
 * ```ts
 * const target = { a: 1, b: 2 };
 * const source1 = { b: 3, c: 4 };
 * const source2 = { d: 5 };
 *
 * const extended = extendObj(target, source1, source2);
 * console.log(extended); // Outputs: { a: 1, b: 3, c: 4, d: 5 }
 * console.log(target);   // Outputs: { a: 1, b: 3 } (target is modified)
 * ```
 * Merges the contents of two or more objects together into the first object.
 * Similar to jQuery's $.extend function.
 * @remarks
 * This function is used to merge the contents of multiple objects into a single object. It takes an optional target object as the first argument and one or more source objects as additional arguments. The function returns the merged object, which is a new object that contains all the properties from the source objects.
 *
 * If the target object is not provided or is not a plain object, an empty object is returned.
 *
 * If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object.
 *
 * If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object.
 * For arrays, The function replaces the contents of the arrays, preserving the original order of the elements.
 * Empty values like null, undefined, and empty strings are ignored.
 */
export declare function extendObj<T extends Record<string, any> = any>(target: any, ...sources: any[]): T;
/**
 * Flattens a nested object structure into a single-level object with dot/bracket notation keys.
 * Handles various data structures including Arrays, Sets, Maps, and plain objects.
 * Skips non-primitive values like functions, class instances.
 *
 * @param {any} obj - The object to flatten
 * @param {string} [prefix=''] - The prefix to use for nested keys
 * @returns {Record<string, Primitive>} A flattened object with primitive values
 *
 * @example
 * // Basic object flattening
 * _flattenObject({
 *   a: {
 *     b: 'value',
 *     c: 42
 *   }
 * })
 * // Returns: { 'a.b': 'value', 'a.c': 42 }
 *
 * @example
 * // Array handling
 * _flattenObject({
 *   items: ['a', 'b', { nested: 'value' }]
 * })
 * // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' }
 *
 * @example
 * // Map handling
 * _flattenObject({
 *   map: new Map([
 *     ['key1', 'value1'],
 *     ['key2', { nested: 'value2' }]
 *   ])
 * })
 * // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' }
 *
 * @example
 * // Complex nested structure
 * _flattenObject({
 *   array: [1, { a: 2 }],
 *   set: new Set(['x', { b: 'y' }]),
 *   map: new Map([['k', { c: 'v' }]]),
 *   obj: {
 *     deep: {
 *       nested: 'value',
 *       fn: () => {}, // Will be skipped
 *       date: new Date() // Will be skipped
 *     }
 *   }
 * })
 * // Returns: {
 * //   'array[0]': 1,
 * //   'array[1].a': 2,
 * //   'set[0]': 'x',
 * //   'set[1].b': 'y',
 * //   'map[k].c': 'v',
 * //   'obj.deep.nested': 'value'
 * // }
 *
 * @throws {Error} Will not throw errors, but silently skips non-primitive values
 *
 * @category Utilities
 * @since 1.0.0
 */
export declare function flattenObject(obj: any, options?: FlattenObjectOptions): Record<string, any>;
/**
 * Checks if a value is an iterable data structure (Array, Set, Map, WeakMap, WeakSet).
 *
 * @param {any} value - The value to check
 * @returns {boolean} True if the value is an iterable structure, false otherwise
 *
 * @example
 * isIterableStructure([1, 2, 3])           // returns true
 * isIterableStructure(new Set([1, 2, 3]))  // returns true
 * isIterableStructure(new Map())           // returns true
 * isIterableStructure({})                  // returns false
 */
export declare function isIterableStructure(value: any): boolean;
/**
 * Enhanced version of Object.entries that preserves key types in TypeScript inference.
 *
 * Unlike the standard Object.entries which types all keys as string, this method
 * maintains the original key types (string | number | symbol) in TypeScript's type system
 * while still following JavaScript's runtime behavior where all keys are strings.
 *
 * @template T - The object type extending Record<string | number, any>
 * @param obj - The object to extract entries from
 * @returns Array of key-value tuples with preserved key types in TypeScript
 *
 * @example
 * ```typescript
 * const obj = { 1: "one", "foo": "bar", 42: "answer" } as const;
 *
 * // Standard Object.entries - all keys typed as string
 * const standard = Object.entries(obj); // [string, string][]
 *
 * // Enhanced Object.typedEntries - preserves original key types
 * const typed = Object.typedEntries(obj);
 * // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[]
 * ```
 *
 * @remarks
 * - Runtime behavior is identical to Object.entries (all keys are strings)
 * - Only TypeScript inference is enhanced to remember original key types
 * - Works best with objects declared with 'as const' for literal type inference
 * - Particularly useful for objects with mixed string and numeric keys
 *
 * @since 1.0.0
 */
export declare function typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{
    [K in keyof T]: [K, T[K]];
}[keyof T]>;
export interface FlattenObjectOptions {
    /**
     * Whether to skip arrays during the flattening process.
     *
     * When set to `true`, arrays will be treated as primitive values and included
     * directly in the flattened result instead of being recursively flattened.
     * This can be useful for performance optimization or when you want to preserve
     * array structures in your flattened output.
     *
     * @default false - Arrays are recursively flattened by default
     *
     * @example
     * ```typescript
     * const obj = {
     *   name: 'John',
     *   tags: ['developer', 'typescript'],
     *   scores: [85, 92, 78]
     * };
     *
     * // Default behavior (skipArrays: false)
     * flattenObject(obj);
     * // Result: { 'name': 'John', 'tags[0]': 'developer', 'tags[1]': 'typescript', 'scores[0]': 85, 'scores[1]': 92, 'scores[2]': 78 }
     *
     * // With skipArrays: true
     * flattenObject(obj, { skipArrays: true });
     * // Result: { 'name': 'John', 'tags': ['developer', 'typescript'], 'scores': [85, 92, 78] }
     * ```
     *
     * @since 1.0.0
     */
    skipArrays?: boolean;
}
