import { TabsData, SingleLevelObject, MultiLevelObject, GenericFunction, GenericArguments } from '../utils/types/index';
export { default as cloneDeep } from 'lodash.clonedeep';
export { default as isEqual } from 'lodash.isequal';

/**
 * @module General
 */

/**
 * This method can be used to check if the variable is empty or not. Returns true if it is empty else false.
 *
 * @param {any} data - Any variable that you want to check if it is empty or not
 *
 * @example
 * ```
 * if(isEmpty(userData)) {
 *   return;
 * }
 * ```
 */
declare function isEmpty(data: any): boolean;
/**
 * This method returns an array of given size filled with provided value
 *
 * @param {number} arraySize - Size of the array i.e number of elements in the array
 * @param {string | number} value - Value that you want to fill in the array
 *
 * @example
 * ```
 * getFilledArray(4,'hello') // ['hello', 'hello', 'hello', 'hello']
 * ```
 */
declare function getFilledArray(arraySize: number, value: string | number): any[];
/**
 * This method returns the index of the selected tab
 *
 * @param {any} tabs - Array of tabs object
 * @param {string} selectedTabName - Selected tab name
 *
 * @remarks
 * Please ensure that tab object has searchId key to facilitate matching process
 *
 * @example
 * ```
 * getSelectedTabIndex(tabsArrayOfObject,'mutual-funds') // 1
 * ```
 */
declare function getSelectedTabIndex(tabs: TabsData[], selectedTabName: string): number;
/**
 * This function can download a file on user's machine either directly by a url or a blob object.
 *
 * @param {
 *  file:File | null;
 *  type:string; fileName:string;
 *  downloadMethod:string;
 *  fileExtension:string;
 *  fileUrl:string | null
 * } downloadConfig
 *
 * @remarks
 *
 * Please ensure you are passing the appropriate downloadMethod type -
 * <br />
 * <br />
 * <p>'url' method expects the fileUrl argument</p>
 * <p>'blob' expects the file argument</p>
 *
 * <br />
 * <h4>downloadConfig properties</h4>
 * <ul>
 *  <li> <span style="font-weight: bold;">file</span> => BlobObject or null. Required if downloadMethod is 'blob' </li>
 *  <li> <span style="font-weight: bold;">type</span> => MIME-TYPE of the file. 'application/pdf', 'application/gzip', 'image/png' </li>
 *  <li> <span style="font-weight: bold;">fileName</span> => Expected name of the downloaded file </li>
 *  <li> <span style="font-weight: bold;">downloadMethod</span> => 'blob' or 'url' </li>
 *  <li> <span style="font-weight: bold;">fileExtension</span> => Expected extension of the downloaded file </li>
 *  <li> <span style="font-weight: bold;">fileUrl</span> => downloadable file's url. Required if downloadMethod is 'url' </li>
 * </ul>
 *
 * @example
 * ```
 * downloadFile({
 *  file: fileBlobObject,
 *  type: 'application/pdf',
 *  fileName: 'MyFile',
 *  fileExtension: 'pdf',
 *  downloadMethod: 'blob',
 *  fileUrl: null
 * }) // *Downloads file of type PDF on the client's machine named MyFile.pdf*
 * ```
 *
 */
declare function downloadFile(downloadConfig: {
    file: File | null;
    type: string;
    fileName: string;
    downloadMethod: string;
    fileExtension: string;
    fileUrl: string | null;
}): void;
/**
 * This method sorts an Object with key value pairs on the basis of the values. (Check examples for better understanding)
 *
 * @param {SingleLevelObject} obj - Object with key value pairs with single level hierarchy. (Read remarks)
 * @param {boolean} isDescending - Sort in descending order or not. Defaults to false. Optional argument.
 *
 * @remarks
 * Object should be of a single level. Avoid nested objects or arrays. In case of error, method returns the original object.
 *
 * @example
 * ```
 * const list = { yellow: 1, blue: 10, red: 5, green: 6, pink: 8 };
 * const listWrong = { yellow: 1, blue: [ 'I', 'am', 'blue' ], red: 5, green: { i: 'i', am: 'am', green: 'green' }, pink: 8 };
 *
 * sortObjectByValue(list, true); // { blue: 10, pink: 8, green: 6, red: 5, yellow: 1 }
 * sortObjectByValue(list); // { yellow: 1, red: 5, green: 6, pink: 8, blue: 10 }
 *
 * sortObjectByValue(listWrong);
 * // console => Error in sorting object, original object returned : ErrorObject
 * // { yellow: 1, blue: [ 'I', 'am', 'blue' ], red: 5, green: { i: 'i', am: 'am', green: 'green' }, pink: 8 }
 * ```
 */
declare function sortObjectByValue(obj: SingleLevelObject, isDescending?: boolean): SingleLevelObject;
declare function getData(obj: any, path: string, def?: null | unknown): any;
/**
 * This method is used to parse an object into entries. Works exactly like Object.entries.
 * Object.entries is still not fully supported so consider this a polyfill for the same.
 *
 * { key1: value1, key2: value2 } => [ [ key1, value1 ], [ key2, value2 ] ]
 *
 * @param {MultiLevelObject} obj - Object to be parsed into entries.
 *
 * @example
 * ```
 * const dummy1 = { key1: value1, key2: value2, key3: value3 };
 * const dummy2 = { key1: 'value1', key2: 'value2', key3: [ 1, 2, 3 ], key4: { a: 1, b: 2 } }
 *
 * getObjectEntries(dummy1) // [ [ key1, value1 ], [ key2, value2 ], [ key3, value3 ] ];
 * getObjectEntries(dummy2) // [ [ key1, value1 ], [ key2, value2 ], [ key3 , [ 1, 2, 3 ] ],[ key4,{ a:1, b:2 } ] ];
 * ```
 */
declare function getObjectEntries(obj: any): any[][];
/**
 * This method searches for an object inside an array of objects based on the object key and expected value then returns its index.
 * Returns -1 if key not found.
 *
 * @param {MultiLevelObject[]} searchArr - Array of objects to search within
 * @param {string} matchKey - Key of the object to be matched
 * @param {MatchValueType} matchValue - Expected value to be matched
 *
 * @remarks
 * <br/>
 * Please ensure not to send chained keys as matchKey.
 * <br/>
 * 'key' | 'name' => Correct
 * <br/>
 * 'key.name[0]' | 'address.pincode' => Incorrect
 *
 * @example
 * ```
 * const dummy = [ { rollNo: 1 }, { rollNo: 2 }, { rollNo: 3 }, { rollNo: 4 } ];
 *
 * getIndexByMatchingObjectValue<number>(dummy, 'rollNo', 4); // 3
 * getIndexByMatchingObjectValue<number>(dummy, 'rollNo', 3); // 2
 * getIndexByMatchingObjectValue<number>(dummy, 'rollNo', 6); // -1
 *
 * getIndexByMatchingObjectValue<number>(dummy, 'address', 6); // -1
 * getIndexByMatchingObjectValue<number>(dummy, 'address.pincode', 6); // -1
 * ```
 */
declare function getIndexByMatchingObjectValue<MatchValueType>(searchArr: MultiLevelObject[], matchKey: string, matchValue: MatchValueType): number;
/**
 * This method returns the path from the url. By default it returns the last path i.e last slash part from the URL.
 * If you want you can get any path from URL by passing index from last value param
 *
 * @param {string} url - The url that is entered
 * @param {number} indexFromLast - The index from last slash in the URL. By default it is the last index.
 *
 * @example
 * ```
 * getPathVariableFromUrlIndex('https://groww.in/mutual-funds/user/explore')       //explore
 * getPathVariableFromUrlIndex('https://groww.in/mutual-funds/user/explore', 2)   //mutual-funds
 * ```
 *
 */
declare function getPathVariableFromUrlIndex(url: string, indexFromLast?: number): string | undefined;
/**
 * This method is used to forcefully delay a function and cancel all intermediate redundant calls made within the span of delay.
 * Returns a method that will debounce by expected delay when called.
 *
 * @param {GenericFunction} func - Method that needs to be debounced
 * @param {number} delay - Amount of delay in miliseconds
 * @param {boolean} leading - A boolean value for if the debounce functions is leading
 * @example
 * ```
 * export function Input() {
 *      const [ query, setQuery ] = useState('');
 *      const [ result, setResult ] = useState([]);
 *
 *      const searchQuery = async (val) => {
 *          const resp = await searchApi(val);
 *          setResult(resp.data);
 *      }
 *
 *      const debouncedSearchQuery = debounce(searchQuery, 500, true);
 *
 *      const onQueryInput = (event) => {
 *          setQuery(event.target.value);
 *          debouncedSearchQuery();
 *      }
 *
 *      const handleKeyDown = (event) => {
 *          // to clear the interval when enter key is pressed, only useful for specific usecases
 *          if(event.key === 'enter'){
 *              debouncedSearchQuery.cance();
 *          }
 *      }
 *
 *      return (
 *          <input
 *              {...props}
 *              handleKeyDown={handleKeyDown}
 *              onChange={onQueryInput}
 *          />
 *      )
 * }
 *
 * // This will result in searchQuery method to be delayed by 500ms.
 * // If the user continues to input query within span of 500ms. Then all redundant calls will cancelled.
 *
 * // Without debounce => 'abcde' => 5 calls individually for a, ab, abc, abcd, abcde
 * // With debounce => 'abcde' => 1 call for abcde
 * ```
 *
 * @remarks
 * the returned callback will have a property named "cancel" to cancel the recurring debounce
 *
 */
declare function debounce(func: GenericFunction, delay?: number, leading?: boolean): {
    (...args: GenericArguments): void;
    cancel(): void;
};
/**
 *
 * This method is used to throttle async functions, and therefore is modified version of the normal throttle
 *
 * @param callback function to throttle
 * @param intervalInMs time interval in microseconds after which the callback is required
 * @returns the original callback but throttled with given interval
 *
 * @example
 * ```
 * // function which gets a resource
 * async function getSomeResource() {
 *    // a resource which takes time
 *    return await new Promise((resolve)=>setTimeout(resolve("your resource"),2000))
 * }
 *
 * // enhancing the function via throttle
 * const throttledFunction = throttle(getSomeResource,5000);
 *
 * // trying to access the resource
 * const printResource = async () => {
 *    const result = throttledFunction();
 *    console.log(result);
 * }
 *
 * printResource() // calling it multiple times to see the behaviour
 *
 * // result: "your resource"
 * ```
 *
 * @remarks
 * this function is specifically designed to handle asynchronous functions
 *
 */
declare function asyncThrottle(callback: GenericFunction, intervalInMs: number): (...args: GenericArguments) => Promise<any>;
/**
 * This method is like `uniq` except that it accepts `iteratee` which is
 * invoked for each element in `array` to generate the criterion by which
 * uniqueness is computed. The order of result values is determined by the
 * order they occur in the array. The iteratee is invoked with one argument:
 * (value).
 *
 * @param arr The array to inspect
 * @param iteratee The iteratee invoked per element.
 *
 * @example
 * ```
 * const arr = [ 12, undefined, { id: 1, name: 'bob' }, null,  { id: 1, name: 'bill' }, null, undefined ];
 *
 * uniqBy(arr, 'name');   // [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }]
 * ```
 */
declare function uniqBy(arr: GenericFunction, iteratee: GenericFunction): any[];
/**
 * Removes values from array using function as predicate. Returns removed values.
 *
 * @param {Array} array
 * @param {function} predicate
 *
 * @returns {Array}
 *
 * @example
 * ```
 * const arr = [ 1, 2, 3, 4, 5, 6 ];
 *
 * const freshArr = remove(arr, (elem) => {
 *    return !!(elem % 2)
 * })
 *
 * // Predicate returned true for every odd value and false for every even value.
 * // For the ones predicate returned true, were deleted from the array. Removed values were returned.
 *
 * // arr = [ 2, 4, 6 ];
 * // freshArr = [ 1, 3, 5 ];
 * ```
 *
 */
declare function remove<T>(array: T[], predicate: (elem: T, index: number, list: T[]) => boolean): T[];
/**
 * Returns new object with copied all properties without the ones specified.
 *
 * @param {MultiLevelObject} object - source object
 * @param {string[]} props - properties to omit
 *
 * @example
 *
 * omit({ name: 'Jack', age: 69, title: 'Mr' }, ['age', 'title']);
 * // { name: 'Jack' }
 *
 * @returns {MultiLevelObject} - new object without given properties
 */
declare function omit(object: MultiLevelObject | null, props: string[]): MultiLevelObject | null;
/**
 * Returns object or array by parsing the string passed based on the parsed type
 *
 * @param {string} filter - source string
 * @param {string[]} defaultValue - [] or {}
 *
 * @example
 *
 * getEntityFiltersFromJSONString('['age', 'title']',[]);
 * // ['age', 'title']
 *
 * @returns {Object | Array} - parsed object or array from the string passed
 */
declare const getEntityFiltersFromJSONString: (filter: string, defaultValue?: Object | [
]) => any;
/**
 * This method is a wrapper over JSON.parse which catches any exceptions if comes
 *
 * @param {string} parameter - source string
 * @param {string} fallback - default value is ''
 * @param {(this: any, key: string, value: any) => any} reviver - this is the reviver method of JSON.parse.
 * Read MDN docs for more on the reviver method:
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_the_reviver_parameter
 *
 * @example
 *
 * parseJSON('{a:'b'}')
 *
 * @returns {Object | Array} - parsed object or array from the string passed
 */
declare const parseJSON: (parameter: string, fallback?: string, reviver?: ((this: any, key: string, value: any) => any) | undefined) => any;
declare const isAllObjectValuesZero: (obj: object) => boolean | undefined;
/**
 * Returns object by removing all the null values from an object or a deeply nested object also without mutating the current object
 *
 * @param {MultiLevelObject} obj - source object
 *
 * @example
 * ```
 * const obj = {
 *  one: null,
 *  two: 2,
 *  three: null,
 *  four: {
 *     five: null
 *   }
 * }
 *
 * removeNullProperties(obj)
 * O/P -
 * newObj = {
 *      two: 2,
 *      four: {}
 *    }
 *
 * ```
 *
 * @returns { Object } - Returns a new object without null values
 */
declare function removeNullProperties(obj: MultiLevelObject): MultiLevelObject;
/**
 * Parses a cookie string into a valid JSON object.
 *
 * @param {cookie} string
 *
 * @example
 * ```
 * const parsedCookieJson = parseCookieToJson('cookie1=some-data;cookie2=other-data') // Output: { cookie1: "some-data", cookie2: "other-data" }
 * ```
 *
 * @returns { Object } - Returns an object which is the json representation of the cookie string
 */
declare function parseCookieToJson(cookie: string | undefined): {
    [key: string]: string;
};

export { asyncThrottle, debounce, downloadFile, getData, getEntityFiltersFromJSONString, getFilledArray, getIndexByMatchingObjectValue, getObjectEntries, getPathVariableFromUrlIndex, getSelectedTabIndex, isAllObjectValuesZero, isEmpty, omit, parseCookieToJson, parseJSON, remove, removeNullProperties, sortObjectByValue, uniqBy };
