import { CATEGORIES_VALUES } from "./enums";
import Logger from "./logger";

const logger = new Logger("[ADOBE OPT-IN]");

const is = (el, type) => typeof el === type;

const toArray = (arg, fallback) => {
    if (arg instanceof Array) {
        return arg;

    } else if (is(arg, "string")) {
        return [arg];
    }

    return fallback || [];
};

const areAllValuesTrue = obj => {
    const keys = Object.keys(obj);
    return !keys.length ? false : keys.every(key => {
        return obj[key] === true;
    });
};

const areValidCategories = catKeys => {
    if (!catKeys || isEmptyArray(catKeys)) {
        return false;
    }
    // `every` will return `true` if empty array, so we guard against it in the previous exp.
    return (toArray(catKeys)).every(cat => {
        return CATEGORIES_VALUES.indexOf(cat) > -1;
    });
};

const toObject = (list, value) => {
    return list.reduce((result, item) => {
        result[item] = value;
        return result;
    }, {});
};

const clone = obj => JSON.parse(JSON.stringify(obj));

const isEmptyArray = arg => Object.prototype.toString.call(arg) === "[object Array]" && !arg.length;

const parse = jsonString => {
    if (isObject(jsonString)) {
        return jsonString;
    }

    try {
        return JSON.parse(jsonString);

    } catch (ex) {
        return {};
    }
};

const areValidPermissions = str => {
    if (str === undefined) { // `existingPermissions` is an optional arg!
        return true;
    }

    return isObject(str) ? areValidCategories(Object.keys(str)) : isStringifiedJsonCategories(str);
};

const isStringifiedJsonCategories = str => {
    try {
        const parsedStr = JSON.parse(str);
        return !!str && is(str, "string") && areValidCategories(Object.keys(parsedStr));
    } catch (ex) {
        return false;
    }
};

const isObject = arg => {
    return arg !== null && is(arg, "object") && Array.isArray(arg) === false;
};

const noop = () => {};

const normalize = param => is(param, "function") ? param() : param;

const handleInvalidPermissions = (permissions, errorMsg) => {
    if (!areValidPermissions(permissions)) {
        logger.error(`${errorMsg}`);
    }
};

const getValues = obj => {
    return Object.keys(obj).map(key => {
        return obj[key];
    });
};

const getUniqueValues = obj => {
    return getValues(obj).filter((v, i, arr) => arr.indexOf(v) === i);
};

export {
    toArray,
    areAllValuesTrue,
    areValidCategories,
    toObject,
    clone,
    parse,
    areValidPermissions,
    noop,
    is,
    normalize,
    handleInvalidPermissions,
    getUniqueValues,
    logger
};
