/**
 * @function createUuid
 */
export function generateUuid(): string { // generate random uuid
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {

        let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);

        return v.toString(16);
    });
}

/**
 * @function findAllIndicesOfCharacter
 * @param {string} value
 * @param {string} character
 */
export function findAllIndicesOfCharacter(value: string, character: string): Array<number> { // find all indeces of given character in string
    let indices = new Array; // result array

    for (let i = 0; i < value.length; i++) { // go through string
        if (value[i] === character) { // check if same character
            indices.push(i); // add index to array
        }
    }

    return indices; // eturn result array
}

/**
 * @function areArraysEqual
 * @param {Array<number>} arr1
 * @param {Array<number>} arr2
 */
export function areArraysEqual(arr1: Array<number>, arr2: Array<number>): boolean {
    if (arr1.length !== arr2.length) return false; // check if the arrays are the same length

    // check if all items exist and are in the same order
    for (var i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) return false;
    }

    return true; // otherwise, return true
}

/**
 * @function allSameType
 * @param {Array<any>} arr
 */
export function allSameType(arr: Array<any>): any { // check if all items in array have the same type
    // note for function: https://stackoverflow.com/questions/49411862/check-if-all-values-of-array-are-of-the-same-type
    return new Set(arr.map(x => typeof x)).size <= 1; // return true or false
}

/**
 * @function getProfilePropertyComparisonOperators
 */
export function getProfilePropertyComparisonOperators(): Array<string> { // get an array of comparison operators used in subconditions 

    const operators = [ // operators in comments don't work
        "equals",
        "notEquals",
        "greaterThan",
        "greaterThanOrEqualTo",
        "lessThan",
        "lessThanOrEqualTo",
        "between",
        "exists",
        "missing",
        "contains",
        "notContains",
        "startsWith",
        "endsWith",
        // "matchesRegex",
        "in",
        "notIn",
        "all",
        // "inContains",
        "hasSomeOf",
        "hasNoneOf",
        // "isDay",
        // "isNotDay"
    ];

    return operators; // return comparison operators
}

/**
* @function getProfileSegmentComparisonOperators
*/
export function getProfileSegmentMatchTypes(): Array<string> { // get an array of comparison operators used in subconditions 

   const matchTypes = [
       "in",
       "notIn",
       "all"
   ];

   return matchTypes; // return match types
}

/**
 * @function flattenObject
 * @param {any} ob
 */
export function flattenObject(ob: any): any { // flatten given object
    var toReturn: { [key: string]: string } = {} // result object

    for (var i in ob) { // go through object
        if (!ob.hasOwnProperty(i)) continue; // 

        if ((typeof ob[i]) == 'object') { // check if property is an object
            if (i != 'fields') { // check if object key is not "fields"
                var a = ob[i]; // 

                if (ob[i].hasOwnProperty('properties')) { //
                    a = ob[i]['properties'] // assign value to a
                }

                var flatObject = flattenObject(a); // 

                for (var x in flatObject) { // go through object
                    if (!flatObject.hasOwnProperty(x)) continue; // 

                    if (x != 'type') { // check if object key is not "type"
                        toReturn[i + '.' + x] = flatObject[x]; // 
                    }

                    else { // object key is "type"
                        toReturn[i] = flatObject[x]; // 
                    }
                }
            }
        } else { // property is not an object
            toReturn[i] = ob[i]; // add property to result object
        }
    }
    return toReturn; // return result object
};

/**
 * @function isItemInList
 * @param {any} listItems
 * @param {any} item
 */
export function isItemInList(listItems: any, item: any): boolean { // check if item in list
    let response = false // false by default

    for (let index in listItems) { // go through each element in list
        if (item.includes(listItems[index])) { // check if item contains an element from list
            response = true;
        }
    }

    return response;
};
