(function (global) {
	global.pulse = {
		rt: {},
		out: {},
		ph: {}
	};
})(this);

var _bcc = _bcc || {};
_bcc.ptns = _bcc.ptns || {};
_bcc.ptns.wmbeacon = {
    "opts": {
        "site_id": "caoa",
        "subAppId": "caoa",
        "marketId": "ca",
        "martId": "b2c",
        "site_version": "d.www.1.0",
        "tm_version": "v0",
        "beacon_format": "",
        "qm_src_default": "https://cdn.quantummetric.com/qscripts/quantum-walmartca.js"
    }
};

(function (bc, config) {
	'use strict';

	// -------------------------------------------------- UTILITY FUNCTIONS --------------------------------------------------
	bc.utils.defKey = '_def';
	bc.utils.separator = '__';

	/**
	 * @description Create a new page view Id
	 * @param {*} data 
	 */
	bc.utils.resetPageViewMetadata = function (data) {
		var curPvId = bc.page_view_id;
		var curOPvId = bc.original_page_view_id;
		try {
			bc.utils.merge(bc.utils, {
				referrer: (data && data.referrer) ? data.referrer : "",
				rumSeq: 0
			})
			bc.original_page_view_id = bc.page_view_id;
			bc.page_view_id = bc.utils.getPageViewId();
		} catch (err) {
			bc.original_page_view_id = curOPvId;
			bc.page_view_id = curPvId;
			bc.utils.error("ERROR: in resetting page view id");
			bc.utils.error(err);
		}
	};

	/**
	 * @desc Merges the current bc.options with some new ones
	 * @desc Check if setOptions has item_category set, in which case update report suite for s_omni object
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Object} options new options to be set
	 * @return {void}
	 */
	bc.utils.setOptions = function (newOptions) {
		bc.utils.merge(bc.options, newOptions);
	};

	// -------------------------------------------------- UTILITY FUNCTIONS --------------------------------------------------
	/**
	 * @desc create cors request if browser supports 
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} method  
	 * @param {String} url  
	 * @return {Object} xhr
	 */
	bc.utils.corsReq = function (method, url) {
		var xhr;
		try {
			xhr = new XMLHttpRequest();
			if ("withCredentials" in xhr) {
				xhr.open(method, url, true);
				xhr.withCredentials = true;
				xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			} else {
				xhr = null;
			}
		} catch (e) { }
		return xhr;
	};

	// -------------------------------------------------- FUNCTIONS TO GET CLIENT DETAILS --------------------------------------------------
	/**
	 * @desc Get client dimension such as viewport width(vW), height(vH) and screen width(sW), height(sH) 
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @return {Object} dimension object
	 */
	bc.utils.clientDim = function () {
		//TODO: Check if these values can be added under cookie
		var dim = {},
			de = document ? document.documentElement : null,
			w = window,
			ws = w ? w.screen : null;
		if (de) {
			dim.vw = de.clientWidth;
			dim.vh = de.clientHeight;
		}
		if (ws) {
			dim.sw = ws.width;
			dim.sh = ws.height;
		}
		if (w) {
			dim.iw = w.innerWidth;
			dim.ih = w.innerHeight;
		}
		return dim;
	};

	bc.utils.hashCode = function (data) {
		var hash = 0, i;
		for (i = 0; i < data.length; i++) {
			hash = (((hash << 5) - hash) + data.charCodeAt(i)) | 0;
		}
		return hash;
	};

	/**
	 * @desc This method is for overrding the default referrer policy
	 * @param {*} elem HTML Element for which refrrer policy will be updated
	 * @returns {Element} HTML Element
	 */
	bc.utils.updateReferrerPolicy = function (elem) {
		try {
			if (elem && (elem.referrerPolicy || elem.referrerPolicy === "")) {
				elem.referrerPolicy = "no-referrer-when-downgrade";
			}
		} catch (err) {
			if (_bcq && _bcq.options && _bcq.options.mode === "debug") {
				bc.utils.log("ERROR: in updating the referrer policy.");
				bc.utils.log(e);
			}
		}
		return elem;
	};

	/**
		 * Merges the attributes sent by the consumer and the templates defined for the action into the parameters for the tag action
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} result with mappings executed and stored under result.out and results.ph
		 * @param {boolean} append_attributes Boolean value whether to append attributes in case there is no mapping
		 * @return {Object} set of params to send for the action
		 */
	bc.utils.getParams = function (attrs, result, append_attributes) {
		var result = result || {},
			variables = result.out || {};
		if (append_attributes) {
			variables = bc.utils.merge(variables, attrs);
		}
		return variables;
	};

	bc.utils.getReferralPvId = function (pv_id) {
		var rpv_id, cpv_id;
		try {
			cpv_id = bc.store.read("cpv_id", 'sessionStorage');
			if (cpv_id && cpv_id !== pv_id) {
				bc.store.write("rpv_id", cpv_id, 'sessionStorage');
			}
			rpv_id = bc.store.read("rpv_id", 'sessionStorage');
			bc.store.write("cpv_id", pv_id, 'sessionStorage');
		}
		catch (e) {
			bc.utils.error("ERROR: in referral page view id setting");
			bc.utils.error(e);
		}
		return rpv_id || "";
	};

	bc.utils.getSeqNum = function () {
		var bstc, seqNum = 1, seqNumCk, seqPrev, bstcPrev;
		try {
			bstc = bc.store.getCookie('bstc');
			seqNumCk = bc.store.read("pulse_seq_num", 'localStorage');
			if (bstc && seqNumCk) {
				bstcPrev = seqNumCk.slice(0,22);
				seqPrev = seqNumCk.slice(22);
				if(bstc === bstcPrev){
					seqNum = seqPrev === "" ? 1 : parseInt(seqPrev, 10) + 1;
				}
			}
			bc.store.write("pulse_seq_num", bstc + seqNum, 'localStorage');
		} catch (e) {
			bc.utils.error("ERROR: in setting seqNum");
			bc.utils.error(e);
		}
		return seqNum || "";
	};

	bc.utils.setGlobalSodPref = function (config) {
		var sodVal = undefined;
		try {
			var sodCookie = bc.store.getCookie("sod");
			if (sodCookie) {
				sodVal = 1;
			}
		} catch (e) {
			bc.utils.error("ERROR: in setting global preference for sod value.");
			bc.utils.error(e);
		}
		window.privPrefData = {
			sod: sodVal
		};
	};

	bc.utils.getReferrerUrl = function () {
		var prevUrl;
		try {
			var referrer = document.referrer;
			var url = document.URL;
			var curUrl = bc.store.read("cur_url", 'sessionStorage');
			if (!curUrl) {
				bc.store.write("prev_url", referrer, 'sessionStorage');
				bc.store.write("cur_url", url, 'sessionStorage');
			} else if (curUrl && url !== curUrl) {
				bc.store.write("prev_url", curUrl, 'sessionStorage');
				bc.store.write("cur_url", url, 'sessionStorage');
			}
			prevUrl = bc.store.read("prev_url", 'sessionStorage');
		}
		catch (e) {
			bc.utils.error("ERROR: in referral page view id setting");
			bc.utils.error(e);
		}
		return prevUrl || "";
	};

	bc.utils.isBlockedURL = function (blockedList, URL) {
		try{
			for (var i = 0; i < blockedList.length; i++) {
				if (blockedList[i].test(URL)) {
					return true;
				}
			}
			return false;
		}
		catch (e) {
			if (_bcq && _bcq.options && _bcq.options.mode === "debug") {
				bc.utils.log("ERROR: could not complete blockedURL check");
				bc.utils.log(e);
			}
		}
	};

	bc.utils.setResetBatching = function () {
		try {
			var wmbeaconHandler = bc.handlers["wmbeacon"];
			if (wmbeaconHandler && wmbeaconHandler.clearBatchInterval && wmbeaconHandler.setBatchInterval) {
				if (bc.pulse_lsck) { // Load shredding cookie exists
					if (bc.pulse_lsck.db) { // Disable batching
						wmbeaconHandler.clearBatchInterval(true);
					} else if (bc.pulse_lsck.ba) { // ba = batch All actions
						bc.options.bConf = {
							b1: {
								bacts: ["pageView", "moduleView", "overlayView", "onLink", "onClick", "performanceMetrics", "performanceMetric", "error", "log", "metric", "ads", "asyncEvent", "message", "referralSource", "scroll"],
								bi: 10000, // batchInterval = 10 Sec
								bmc: 10, // batchMaxCount = Max number of events in a batch
								bbs: 700000 // batchByteSize = Max number of characters in a batch (700 KB)
							}
						};
						wmbeaconHandler.setBatchInterval(true);
					} else if (bc.pulse_lsck.bConf && Object.keys(bc.pulse_lsck.bConf).length > 0) { // Specific config is there related to batching.
						bc.options.bConf = Object.assign({}, bc.pulse_lsck.bConf);
						wmbeaconHandler.setBatchInterval(true);
					} else { // Load shredding cookie present, but no config releated to batching. So we will use the default batching config now. 
						bc.options.bConf = Object.assign({}, bc.options.default_bConf);
						wmbeaconHandler.setBatchInterval(true);
					}
				} else { // Load shredding cookie is not there. So we will use the default batching config now. 
					bc.options.bConf = Object.assign({}, bc.options.default_bConf);
					wmbeaconHandler.setBatchInterval(true);
				}
			}
		} catch (e) {
			bc.utils.log("ERROR: could not complete setting resetting batching");
			bc.utils.log(e);
		}
	};

	bc.utils.readPulseConfigCookie = function () {
		bc.pulse_lsck = bc.pulse_lsck || undefined;
		bc.pulse_lsck_raw = bc.pulse_lsck_raw || undefined;
		bc.pulse_lsck_changed = false;
		bc.cookieTimer = bc.cookieTimer || null;
		try {
			var ckCur = bc.store.getCookie("pulse_lsck");
			if (ckCur !== bc.pulse_lsck_raw) { // Change in cookie value has happened.
				bc.pulse_lsck_raw = ckCur || undefined;
				bc.pulse_lsck = ckCur ? JSON.parse(window.atob(ckCur)) : undefined;
				bc.pulse_lsck_changed = true;
			}
		}
		catch (e) {
			bc.pulse_lsck = undefined;
			bc.pulse_lsck_raw = undefined;
			bc.pulse_lsck_changed = false;
			bc.push(['_tagAction', "pulseInternal", "error", "lsCookieError", {}]);
			bc.utils.log("ERROR: could not complete ReadPulseCookie");
			bc.utils.log(e);
		}
		return bc.pulse_lsck;
	};

	bc.utils.runCookieTimer = function () {
		bc.pulse_lsck = bc.pulse_lsck || undefined;
		bc.cookieTimer = bc.cookieTimer || null;
		try {
			bc.utils.log("Set runCookieTimer to read pulse_lsck cookie");
			clearInterval(bc.cookieTimer);
			bc.cookieTimer = setInterval(function () {
				bc.utils.log("Running runCookieTimer to read pulse_lsck cookie");
				bc.utils.readPulseConfigCookie();
				// Set/Reset batching based on the new cookie status
				if (bc.pulse_lsck_changed === true) { // Change in cookie value has happened.
					bc.utils.log("pulse_lsck cookie got a new value.We need to set/reset batching");
					bc.utils.setResetBatching();
					bc.pulse_lsck_changed = false;
				}
			}, 2 * 60000);
		}
		catch (e) {
			bc.utils.log("ERROR: could not complete runCookieTimer");
			bc.utils.log(e);
		}
	};

  bc.utils.getContextInfo = function () {
    bc.runtimeConfig = bc.runtimeConfig || undefined;
    var returnVal = {};
    if (bc && bc.runtimeConfig) {
      returnVal = bc.runtimeConfig;
    } else {
      try {
        var runtimeConfig = {};
        if (window.__NEXT_DATA__) {
          runtimeConfig = window.__NEXT_DATA__.runtimeConfig;
        } else {
          var nextEl = document.getElementById("__NEXT_DATA__");
          var text = nextEl && nextEl.textContent;
          var contextInfo = JSON.parse(text || "{}");
          runtimeConfig = contextInfo.runtimeConfig;
        }
        returnVal = {
          appVersion: runtimeConfig.appVersion,
          dataCenter: runtimeConfig.dataCenter
        }
        bc.runtimeConfig = returnVal;
      } catch (e) {
        returnVal = {};
        bc.runtimeConfig = undefined;
        bc.utils.log("ERROR: Getting getContextInfo");
        bc.utils.log(e);
      }
    }
    return returnVal;
  };

  	bc.utils.getTopics = function () {
		try{
			if (document.browsingTopics) {
				document.browsingTopics()
				.then(function(topics) {
					bc.options.topics = topics;
				})
				.catch(function(err) {
					bc.utils.log("ERROR: Retrieving topics");
					bc.utils.log(err);
				})
			}
		}
		catch (e) {
			if (_bcq && _bcq.options && _bcq.options.mode === "debug") {
				bc.utils.log("ERROR: getting topics array");
				bc.utils.log(e);
			}
		}
	};

})(_bcq, _bcc);

(function (bc, config) {
	'use strict';
	bc.batchUtils = bc.batchUtils || {};
	// -------------------------------------------------- UTILITY FUNCTIONS FOR BATCH PROCESSING--------------------------------------------------
	bc.batchUtils.getBatchFlag = function (action) {
		var flag = undefined;
		try {
			if (bc && bc.options && bc.options.bConf && Object.keys(bc.options.bConf).length > 0) {
				var bConf = bc.options.bConf;
				var batchNames = Object.keys(bConf);
				var totalBatches = batchNames.length;
				for (var count = 0; count < totalBatches; count++) {
					var eachBatchName = batchNames[count];
					var eachBatch = bConf[eachBatchName];
					if (eachBatch && eachBatch.bacts && eachBatch.bacts.indexOf(action) >= 0) {
						flag = eachBatchName;
					}
				}
			}
		}
		catch (e) {
			bc.utils.error("ERROR: in getBatchFlag");
			bc.utils.error(e);
		}
		return flag;
	};

	bc.batchUtils.getQsByteSize = function (qs) {
		var byteSize = 0;
		try {
			byteSize = qs ? new Blob([qs]).size : 0;
		}
		catch (e) {
			byteSize = qs ? qs.length : 0;
			bc.utils.error("ERROR: in getQsByteSize");
			bc.utils.error(e);
		}
		return byteSize + 50; // Adding extra 50 to have the hc length
	};

	bc.batchUtils.readBatchEvtFromStorage = function () {
		var existingList = {};
		try {
			existingList = bc.store.read("batch_evts", 'sessionStorage') || {};
		} catch (e) {
			bc.utils.error("ERROR: in readBatchEvtFromStorage");
			bc.utils.error(e);
		}
		return existingList;
	};

	bc.batchUtils.writeBatchEvtToStorage = function (batchName, reqList, reqListByteSize) {
		try {
			var existingList = bc.batchUtils.readBatchEvtFromStorage();
			if (reqList && reqListByteSize) {
				existingList[batchName] = {
					reqList: reqList,
					reqListByteSize: reqListByteSize
				}
			} else {
				existingList[batchName] = undefined;
			}
			bc.store.write("batch_evts", existingList, 'sessionStorage');
		} catch (e) {
			bc.utils.error("ERROR: in writeBatchEvtToStorage");
			bc.utils.error(e);
		}
	};

	bc.batchUtils.getBatchSeqNum = function () {
		var bstc, batchSeqNum = 1, bSeqNumCk, bSeqPrev, bstcPrev;
		try {
			bstc = bc.store.getCookie('bstc');
			bSeqNumCk = bc.store.read("pulse_batch_seq_num", 'localStorage');
			if (bstc && bSeqNumCk) {
				bstcPrev = bSeqNumCk.slice(0, 22);
				bSeqPrev = bSeqNumCk.slice(22);
				if (bstc === bstcPrev) {
					batchSeqNum = bSeqPrev === "" ? 1 : parseInt(bSeqPrev, 10) + 1;
				}
			}
			bc.store.write("pulse_batch_seq_num", bstc + batchSeqNum, 'localStorage');
		} catch (e) {
			bc.utils.error("ERROR: in setting batchSeqNum");
			bc.utils.error(e);
		}
		return batchSeqNum || "";
	};
})(_bcq, _bcc);
(function (bc, config) {
    'use strict';
    bc.utils = bc.utils || {};
    var commonErr = "\n\nNumber of arguments can be either 3 or 4." +
        "\n\ncontext,action and name are mandatory fields and should not be empty." +
        "\n\nIf looking in VAST, please enter the nm.nm value in the name field.";
    var ctxActErr = "\n\nIt is a mandatory field and should not be empty." +
        "\n\nNo special character allowed." +
        "\n\nIt should be string value and should not exceed more than 25 characters in length." +
        "\n\nIt should follow the camelCase naming convention." +
        "\n\nSample values: homePage, productPage.";
    var nameErr = "\n\nIt is a mandatory field and should not be empty." +
        "\n\nShould not exceed more than 50 characters in length." +
        "\n\nSpace is not allowed with name." +
        "\n\nIf looking in VAST, please enter the nm.nm value in the name field.";
    var attrErr = "\n\nIt is an optional field." +
        "\n\nIt should be a JSON object and the first level key's values should only contain Array or JSON." +
        "\n\nAll first level keys should be less than 3 characters length." +
        "\n\nAll the keys in this JSON should be abbreviative string keys. for eg: pr, se, fe ,sl ,rec and ads.";
    var CTX_BLACK_LIST = ["pageSpecfic"];
    var ACT_WHITE_LIST = ["pageView", "moduleView", "overlayView", "onLink", "onClick", "performanceMetrics", "performanceMetric", "error", "log", "metric", "ads", "asyncEvent", "message", "referralSource", "scroll"];
    var SPECIFIC_ACT_CTX = {
        "log": ["walmartWeb"],
        "metric": ["walmartWeb"]
    };
    /**
     * @desc definition of the validateCtx util method
     * @desc this method validates the context passed to _tagAction
     * @desc ctx is mandatory && should be <= 25 chars
     * @desc Should follow camel casing
     * @desc No special character or space allowed.
     * @param {String} ctx
     * @return {boolean}
     */
    bc.utils.validateCtx = function (ctx) {
        if (ctx) {
            var regx = /^[a-z][a-zA-Z]*$/;
            if (typeof ctx !== 'string' ||
                ctx.trim().length === 0 ||
                ctx.trim().length > 25) {
                return false;
            }
            return regx.test(ctx);
        }
        return false;
    };

    /**
     * @desc definition of the validateName util method
     * @desc this method validates the name passed to _tagAction
     * @desc name is mandatory
     * @desc should be <= 50 chars if passed
     * @desc No space allowed
     * @param {String} name
     * @return {boolean}
     */

    // Space not allowed
    bc.utils.validateName = function (name) {
        if (name) {
            var spaceRegx = /\s/;
            if (typeof name !== 'string' ||
                name.trim().length === 0 ||
                name.trim().length > 50) {
                return false;
            }
            return !spaceRegx.test(name);
        }
        return false;
    };

    /**
     * @desc definition of the validateData util method
     * @desc this method validates the data passed to _tagAction
     * @desc data are optional
     * @desc Should be a valid JSON if passed
     * @desc All the level1 keys should be <=3 char length
     * @desc All the level1 values should be Object(either JSON or array)
     * @param {String} data
     * @return {boolean}
     */
    bc.utils.validateData = function (data) {
        if (data) {
            if (typeof data !== 'object' || Array.isArray(data) === true) {
                return false;
            }
            var flag = true, topKeys = Object.keys(data);
            topKeys.forEach(function (eachKey) {
                if (eachKey.length > 3 || typeof data[eachKey] !== 'object') {
                    flag = false;
                }
            });
            return flag;
        }
        return true;
    };


    /**
     * @desc definition of the checkSpecCtxAct util method
     * @desc Checks if any action is allowed with any specific context or not from SPECIFIC_ACT_CTX
     * @param {String} context
     * @param {String} action
     * @return {boolean}
     */
    bc.utils.checkSpecCtxAct = function (ctx, act) {
        if (SPECIFIC_ACT_CTX[act]) {
            if (SPECIFIC_ACT_CTX[act].indexOf(ctx) >= 0) {
                return true;
            }
            return false;
        }
        return true;
    }

    /**
     * @desc definition of the validateArgs util method
     * @desc this method validates the argumants passed to _tagAction
     * @desc argument lenght should either 3 or 4 based on whether attribute is passed or not.
     * @desc ctx mandatory && should be <= 25 chars
     * @desc ctx should not be in CTX_BLACK_LIST
     * @desc ctx should follow camel casing
     * @desc No special character or space allowed in context
     * @desc act is mandatory and should be one of ACT_WHITE_LIST
     * @desc name is mandatory and should be <=50 chars
     * @desc attrs optional but should be a JSON is passed
     * @param {Array} input Array of the arguments
     * @return {Object}
     */
    bc.utils.validateArgs = function (input) {
        var status = {
            isValid: false
        };
        try {
            if (input.length < 3 || input.length > 4) {
                status.message = commonErr;
            } else {
                var ctx = input[0],
                    act = input[1],
                    name = input[2],
                    attrs = input[3];
                if (bc.utils.validateCtx(ctx) === false) {
                    status.message = "Beacon Error: Context should satisfy following points." + ctxActErr;
                } else if (CTX_BLACK_LIST.indexOf(ctx) >= 0) {
                    status.message = "Beacon Error: You have passed one of the black list contexts.";
                } else if (ACT_WHITE_LIST.indexOf(act) === -1) {
                    status.message = "Beacon Error: Action " + act + " is not in the allowed list. \n\n Allowed action list: " + ACT_WHITE_LIST;
                } else if (bc.utils.checkSpecCtxAct(ctx, act) === false) {
                    status.message = "Beacon Error: Action " + act + " is not in the allowed with context " + ctx;
                } else if (bc.utils.validateName(name) === false) {
                    status.message = "Beacon Error: Name should satisfy following points." + nameErr;
                } else if (bc.utils.validateData(attrs) === false) {
                    status.message = "Beacon Error: Data should satisfy following points." + attrErr;
                } else {
                    try {
                        status = {
                            isValid: true,
                            ctx: ctx,
                            act: act,
                            name: name,
                            attrs: attrs ? JSON.parse(JSON.stringify(attrs)) : {}
                        }
                    } catch (e) {
                        status.isValid = false;
                        status.message = "You have passed an invalid JSON in attribute";
                    }
                }
            }
        } catch (err) {
            status.message = "Error in validating the arguments";
        }
        return status;
    }
})(_bcq, _bcc);

(function (bc) {
    'use strict';
    bc.mitigationUtils = bc.mitigationUtils || {};
    // var pulse_lsck = {
    //     da: true, // disable ads
    //     dq: true, // disable quantum
    //     db: true, // disable batch
    //     ba: true, // batch all actions
    //     bConf: {  // batch config
    //         b1: {
    //             bacts: ['performanceMetrics', 'performanceMetric', 'ads']
    //         }
    //     },
    //     wl: { // Whitelist action context list
    //         "pageView": ["*"],
    //         "onClick": ["homePage", "itemPage"]
    //     },
    //     bl: { // Black list action context list
    //         "overlayView": ["cart", "browse"],
    //         "asyncEvent": ["browse"],
    //         "log": ["*"]
    //     }
    // };

    bc.mitigationUtils.checkWhiteListActionCtxs = function (wl, act, ctx) {
        var ctxList = Array.isArray(wl[act]) ? wl[act] : [];
        if (ctxList.indexOf("*") >= 0 || ctxList.indexOf(ctx) >= 0) {
            return true;
        }
        return false;
    };

    bc.mitigationUtils.checkBlackListActionCtxs = function (bl, act, ctx) {
        var ctxList = Array.isArray(bl[act]) ? bl[act] : [];
        if (ctxList.indexOf("*") >= 0 || ctxList.indexOf(ctx) >= 0) {
            return false;
        }
        return true;
    };

    bc.mitigationUtils.checkBeaconAllowance = function (shardingCookie, ctx, act) {
        try {
            if (shardingCookie) {
                var wl = shardingCookie.wl; // Whitelist of action context combination
                var bl = shardingCookie.bl; // Blacklist of action context combination
                if (wl) {
                    return bc.mitigationUtils.checkWhiteListActionCtxs(wl, act, ctx);
                } else if (bl) {
                    return bc.mitigationUtils.checkBlackListActionCtxs(bl, act, ctx)
                } else {
                    return true;
                }
            } else {
                return true;
            }
        } catch (e) {
            bc.utils.log("ERROR: could not complete checkBeaconAllowance");
            bc.utils.log(e);
            return true;
        }
    };
})(_bcq);
(function (bc, config) {
	'use strict';
	// -------------------------------------------------- Commands Definition --------------------------------------------------
	/**
	 * @desc reset pageView metadata
	 * @author pmanghn <pmanghn@walmartlabs.com>
	 * @param {Object} options new options to be set
	 * @return {void}
	 */
	bc.commands._resetPageViewMetadata = function (options) {
		bc.utils.resetPageViewMetadata.apply(bc, arguments);
	};

	/**
	 * @desc Merges the current bc.options with some new ones
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Object} options new options to be set
	 * @return {void}
	 */
	bc.commands._setOptions = function () {
		bc.utils.setOptions.apply(bc, arguments);
	};

	/**
	 * @desc definition of the tagAction Command 
	 * @desc sends the beacon attributes to each of the partners for it's subsequent tagging.
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context Optional namespace about the location of the action
	 * @param {String} action Name of the Action to be tagged.
	 * @param {String} report Name of the Report Id for filtering purpose.
	 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
	 * @return {Array} 
	 */

	bc.commands._tagAction = function () {
        var args = Array.prototype.slice.call(arguments);
		var fifthArg = args.length === 5 ? args.pop() : false,
			onlyPtnsMappings = typeof fifthArg === "boolean" ? fifthArg : false,
			status = bc.utils.validateArgs ? bc.utils.validateArgs(args) : {};
		if (status && status.isValid && status.isValid === true) {
			var pn, // Partner's Name iterator
				count = 0,
				ctx = status.ctx || '',
				act = status.act || '',
				name = status.name || '',
				attrs = status.attrs || {};
			// Check if this context and action combination is allowed or not
			try{
				if(bc.pulse_lsck && bc.mitigationUtils.checkBeaconAllowance && bc.mitigationUtils.checkBeaconAllowance(bc.pulse_lsck,ctx,act) === false){
					bc.utils.log("Context: " + ctx + " and action: " + act + " is not allowed because of mitigation");
					return 0;
				}
			}catch(e){}
			// Ends here context and action combination

			bc.utils.rumSeq = typeof (bc.utils.rumSeq) === 'number' ? ++bc.utils.rumSeq : 1;

			// If the rum-mappings is not loaded and we receive tagAction request,
			// then keep the list of the those requests so that we can run them once the
			// partner handlers are ready.
			// When partner handlers will be ready, isPtnsMappingsLoaded -> true
			if (bc.isPtnsMappingsLoaded === false) {
				var tmpData = {
					ctx: ctx,
					act: act,
					name: name,
					attrs: Object.assign({}, attrs)
				};
				tmpData ? bc.pendingPtnsmappingsQueue.push(tmpData) : null;
			}

			// ------------------------------
			// For each of the Partner Handlers, tag the action with all of the data.
			for (pn in bc.handlers) {
				// If we are executing the pending partner requests and partner is "wmbeacon",
				// then we need to continue as wmbeacon partner is already executed for those requests. 
				if (onlyPtnsMappings === true && pn === "wmbeacon") {
					continue;
				}
				try{
					if(bc.pulse_lsck){
						if (pn === "ads" && bc.pulse_lsck.da) {
							continue;
						}
					}
				}catch(e){}
				try {
					if (pn === "qm" && !bc.loadQM) {
						continue;
					}
				} catch (e) { }
				try {
					if (pn === "ads" && window.privPrefData && window.privPrefData.sod === 1)  {
						continue;
					}
				}
				catch (err) {
					bc.utils.log("ERROR: Retrieving sod cookie value");
				}

				var currentURL = window.location.href;
				var blockedURLs = _bcc.ptns[pn].blockedURLs || [];
				if (bc.utils.isBlockedURL(blockedURLs, currentURL)) {
					continue;
				}

				if (bc.handlers.hasOwnProperty(pn)) {
					attrs = bc.handlers[pn].setReferrer(attrs);
					attrs = bc.handlers[pn].metadata(attrs, ctx, act, name);
					count += bc.handlers[pn].tagAction(ctx, act, name, attrs, pn);
				}
			}
			if (count === 0) {
				bc.utils.warn(); ('WARNING - Action [' + act + '] under context [' + ctx + '] was not tagged by any Partners');
			}
			return count;
		} else {
			bc.utils.error(status.message || "Error occured while processing the command");
			return 0;
		}
	};

	/**
	 * @description Infamous "push". Based on the push function from Google Analytics. Receives arrays of commands as parameters
	 * @description and executes a specifc function from the bc.commands namespace if possible
	 * @description inspired from: https://developers.google.com/analytics/devguides/collection/gajs/
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Array} an array or list of arrays containing at least the command to be executed
	 * @return void
	 */
	bc.push = function () {
		var args = arguments;
		function the_push() {
			var i, cmd, name;
			// ------------------------------
			// Iterate through the arguments as people can add one or more 
			// commands Make sure that all of the commands are Arrays and 
			// that have at least one entry (the name of the command)
			for (i = 0; i < args.length; ++i) {
				cmd = args[i];
				if (bc.apiq) {
					bc.apiq.push(cmd);
				}
				if (Array.isArray(cmd) && cmd.length) {
					name = cmd[0];
					if (bc.commands.hasOwnProperty(name)) {
						bc.commands[name].apply(bc, cmd.slice(1));
					} else {
						bc.utils.error('No such command found with name : ' + name);
					}
				}
			}
		}
		// ------------------------------
		// Add a timeout(0) to the "push" functionality (if enabled), so that all of the analytics code goes 
		// into the queue of the browser's thread so that it gets executed whenever the browser has some spare time
		if (bc.options.push_timeout === true) {
			window.setTimeout(the_push, 0);
		} else {
			the_push();
		}
	};
})(_bcq, _bcc);
(function (bc) {
	'use strict';
	// ------------------ Store Definition ------------------ //

	bc.store = bc.store || {};
	bc.store.prefix = '_bc_';

	bc.store.read = function (name, option) {
		var storage = window[option];
		var key = bc.store.prefix + name;
		try {
			return JSON.parse(storage.getItem(key)).data;
		}
		catch (err) {
			return undefined;
		}
	};

	bc.store.write = function (key, value, option) {
		if (!key) {
			bc.utils.error('No [key] found while performing write operation on storage');
			return;
		}
		var storage = window[option];
		key = bc.store.prefix + key;
		if (typeof value === 'undefined' || value === null) {
			storage.removeItem(key);
		}
		else {
			try {
				storage.setItem(key, JSON.stringify({data: value}));
			} catch (err) {
				bc.utils.warn(); ('WARNING: Store write operation failed for key [' + key + ']');
			}
		}
	};

	// ------------------ Cookie Definition ------------------ //

	/**
	 * @desc Get cookie value
	 * @desc Which value to fetch from cookie depends on number of parameters passed to this function
	 * @desc arguments length < 1 or single argument 'name' as null or undefined, return all name/value stored in cookie
	 * @desc arguments length < 2, to get all properties name/value from a cookie value with a given 'name'
	 * @desc arguments length < 3, to get a value of a particular 'property' from cookie value with a given 'name'
	 * @desc Anytime 'name' is null or undefined, means return object with all the name/value from cookie
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} name of cookie
	 * @param {String} separator by which property name and value are separated in single cookie value
	 * @param {String} property name to be fetched from cookie value
	 * @return {Mixed} value of cookie based on provided params
	 */
	bc.store.getCookie = function (name, separator, property) {
		var ckArr = document.cookie.split(';'),
			i,
			len = ckArr.length,
			ck,
			ckNm,
			result = {},
			ckVal,
			prop;
		for (i = 0; i < len; i++) {
			ck = ckArr[i].split('=') || [];
			ckNm = (typeof ck[0] === 'string') ? ck[0] : null;
			result[ckNm.trim()] = ckArr[i].replace(ckNm + '=', '');
		}
		if (arguments.length > 0 && name) {
			ckVal = result[name];
			if (typeof ckVal !== 'string' || !ckVal || !separator) {
				return ckVal;
			}
			result = {};
			ckVal = ckVal.split(separator) || [];
			len = ckVal.length;
			for (i = 0; i < len; i++) {
				prop = (typeof ckVal[i] === 'string') ? ckVal[i].split('=') : [];
				result[prop[0].trim()] = ckVal[i].replace(prop[0] + '=', '');
			}
			if (arguments.length > 2) {
				return result[property];
			}
		}
		return result;
	};
	/**
	 * @desc Set simple cookie with given options object, cookie format nm1=vl1
	 * @desc All params to function are required params, send 'value' as 'null' to make that cookie expire
	 * @desc If 'value' is null or undefined means make that cookie expire
	 * @desc If 'value' is an object, it will store as stringified JSON
	 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} name cookie name
	 * @param {Mixed} value cookie value
	 * @param {Object} options which specifies details for domain/expires/path/secure
	 * @return void
	 */
	//TODO: Discuss whether to provide this options - Calculate RISK while updating cookie
	//Is the cookie already available ? are the new expiry, domain, path correct and match with existing cookie options
	//Whats the format of existing cookie ? Is the update following same format
	//Is the cookie following any encoding format? 
	//While updating secure cookie, can not read existing value, In this case complete value has to be updated
	//Can everyone write all cookies ? What are the restrictions to be included here.
	bc.store.setCookie = function (name, value, options) {
		var result, exp;

		//Keep setCookie params as very strict, all are required
		if (!name || !options) {
			bc.utils.error('Not enough information to perform setCookie operation');
			return;
		}
		//If value is undefined or null then remove that cookie
		if (!value) {
			value = null;
			exp = new Date(0);
		} else {
			if (typeof options.expires === "number") {
				exp = new Date();
				exp.setTime(options.expires);
			}
		}
		result = name + (value ? "=" + value : value) +
			";path=" + (options.path || "/") +
			(options.domain ? ";domain=" + options.domain : "") +
			((exp && options.setExpire) ? ";expires=" + exp.toUTCString() : "") +
			(options.secure ? ";secure" : "");

		document.cookie = result;
	};

})(_bcq);
(function (bc) {
    bc.qmUtils = bc.qmUtils || {};
    bc.qmUtils.loadQmLib = function (cdnPath) {
        function installQuantum() {
            setTimeout(function () {
                var qtm = document.createElement('script');
                qtm.type = 'text/javascript';
                qtm.async = 'async';
                qtm.defer = 'defer';
                qtm.src = cdnPath;
                !window.QuantumMetricAPI && document.head.appendChild(qtm);
                window.removeEventListener('load', installQuantum);
            }, 0);
        }
        var loaded = !!performance.getEntriesByType('navigation')[0].loadEventEnd;
        if (loaded) {
            installQuantum();
        } else {
            window.addEventListener('load', installQuantum);
        }
        window["QuantumMetricOnload"] = function () {
            QuantumMetricAPI.addEventListener("start", function () {
                bc.utils.log('Quantum library loaded successfully');
                // Read the global variable if any data pending to be sent.
                try {
                    var existingData = bc.pendingQmData || [];
                    if (window && window.QuantumMetricAPI && existingData && existingData.length > 0) {
                        for (var count = 0; count < existingData.length; count++) {
                            var qmInput = existingData[count];
                            if (qmInput && Array.isArray(qmInput)) {
                                window.QuantumMetricAPI.sendEvent.apply(window.QuantumMetricAPI, qmInput);
                            }
                        }
                        bc.pendingQmData = [];
                    }
                } catch (err) {
                    bc.utils.error("ERROR: in triggerQmSend");
                    bc.utils.error(err);
                }
            });
        };
    };
    bc.qmUtils.loadQmFromCDN = function () {
        bc.pulse_lsck = bc.pulse_lsck || undefined;
        bc.loadQM = bc.loadQM || true;
        try {
            var wmBeaconConfig = _bcc.ptns.wmbeacon.opts || {};
            var isQmCompatibleBh = wmBeaconConfig["qm_support"];
			      var qmDefaultSource = wmBeaconConfig["qm_src_default"]; // Default QM Source for tenant if not specified by FE.
            var qms = bc.options.qms; // QM Source for tenant specified by FE through _setOptions
            // if pulse_lsck.dq is true, then qm will be disabled.
            // If the bh supports qm -> Then qm will be loaded and it won't check any other cookie.
            // Or else we will check if qme cookie set from lua on page load for that user session
            // if qme cookie set -> Then QM will be loaed else not loaded.
            // If the qms passed from FE -> Then qm will be loaded
            if (bc.pulse_lsck && bc.pulse_lsck.dq === true) {
                bc.loadQM = false
            } else if (isQmCompatibleBh) {
                bc.loadQM = true;
            } else if (qms) {
              bc.loadQM = true;
            } else {
              var qme = bc.store.getCookie("qme");
              bc.loadQM = !!qme;
            }
            if (bc.loadQM) {
                var cdnPath = qms ? qms : qmDefaultSource
                bc.qmUtils.loadQmLib(cdnPath)
            }
        } catch (e) {
            bc.loadQM = false
            bc.utils.log("ERROR: could not complete loadQmFromCDN");
            bc.utils.log(e);
        }
        return bc.loadQM
    };
})(_bcq);
(function (bc) {
	'use strict';
	bc.mappingsExecuter = bc.mappingsExecuter || {};
	var mappingFuns = {
		/**
		 * 
		 * @description This method executes the mapping functions for diffrent partners.
		 * @param {*} funName: Name of the fucntion to be executed
		 * @param {*} attrs: Input data attribute from _tagAction
		 * @returns {Object} 
		 */
		executeFn: function (funName, attrs) {
			bc.utils.log("Inside Execute Function");
			var result = {
				out: {},
				ph: {}
			};
			try {
				pulse.out = {};
				pulse.ph = {};
				if (pulse && pulse.rt && pulse.rt[funName]) {
					pulse.rt[funName].apply(null, [attrs]);
					result.out = pulse.out;
					result.ph = pulse.ph;
				}
			} catch (err) {
				bc.utils.error("Error occurred in mapping");
				bc.utils.error("----Mapping Object----");
				bc.utils.error(funName);
				bc.utils.error("----Error Detail----");
				bc.utils.error(err);
			}
			return result;
		},
		/**
		 * 
		 * @param {*} ctx: Context 
		 * @param {*} act: action
		 * @param {*} attrs: data attribute 
		 * @param {*} pn: partner name 
		 * @returns {Object}
		 */
		executeMapping: function (ctx, act, attrs, pn) {
			bc.utils.log("Inside Execute Mappings");
			var funName = pn + "_" + act + "_" + ctx,
				result = bc.mappingsExecuter.executeFn(funName, attrs);
			return result;
		},
		/**
		 * 
		 * @description Placeholder for the "validate" function of the Partner Handlers
		 * @param {*} ctx: Context 
		 * @param {*} act: action
		 * @param {*} attrs: data attribute 
		 * @param {*} pn: partner name 
		 * @returns {boolean}
		 */
		// executeVldt: function (ctx, act, attrs, pn) {
		// 	bc.utils.log("Inside Execute Vldt");
		// 	var validate = true,
		// 		funName = "vldt_" + pn + "_" + act + "_" + ctx,
		// 		result = bc.mappingsExecuter.executeFn(funName, attrs);
		// 	validate = result && result.out && result.out.validate === false ? false : true;
		// 	return validate;
		// },
		/**
		 * 
		 * @description Placeholder for the "afterTag" function of the Partner Handlers
		 * @param {*} ctx: Context 
		 * @param {*} act: action
		 * @param {*} attrs: data attribute 
		 * @param {*} pn: partner name 
		 * @returns {boolean} 
		 */
		// executeAfterTag: function (ctx, act, attrs, pn) {
		// 	bc.utils.log("Inside Execute After Tag");
		// 	var funName = "af_" + pn + "_" + act + "_" + ctx,
		// 		result = bc.mappingsExecuter.executeFn(funName, attrs);
		// 	return result;
		// }
	}
	bc.utils.merge(bc.mappingsExecuter, mappingFuns);
})(_bcq);
// nativeInterpreter.js
(function (bc, mp) {
    'use strict';
    [
        'Array.isArray',
        'Array.prototype.includes',
        'Array.prototype.join',
        'Array.prototype.pop',
        'Array.prototype.push',
        'Array.prototype.shift',
        'Array.prototype.unshift',
        'Array.prototype.splice',
        'Array.prototype.sort',
        // 'Array.prototype.concat',
        // 'Array.prototype.slice',
        // 'Array.prototype.toString',
        // 'Boolean.prototype.toString',
        // 'Number.prototype.toString',
        // 'Number.prototype.toFixed',
        // 'Number.prototype.parseFloat',
        'String.prototype.replace',
        'String.prototype.split',
        'String.prototype.match',
        // 'String.prototype.uppercase',
        // 'String.prototype.lowercase',
        // 'String.prototype.substr',
        // 'String.prototype.substring',
        // 'String.prototype.slice',
        // 'String.prototype.concat',
        // 'String.prototype.indexOf',
        // TODO: length operator (should apply for Array and String objects)
        // TODO: typeof operator
    ].forEach(function (field) {
        try {
            var split = Array.isArray(field) ? field[0].split('.') : field.split('.');
            var type = split[0];
            if (['Array', 'Boolean', 'Number', 'Object', 'String'].indexOf(type) === -1) {
                return;
            }
            var theFunction = window[type];
            var isPrototype = split[1] === 'prototype';
            if (isPrototype && !theFunction.prototype) {
                return;
            }
            if (isPrototype) {
                theFunction = theFunction.prototype;
            }
            var nativeMethodName = split[isPrototype ? 2 : 1];
            // TODO: change the name of this variable once the shortened version of rt is implemented
            var rtMethodName = Array.isArray(field) ? field[1] : nativeMethodName;
            if (!theFunction[nativeMethodName] || !theFunction[nativeMethodName].apply) {
                return;
            }
            mp[rtMethodName] = function () {
                try {
                    return theFunction[nativeMethodName].apply(arguments[0], Array.prototype.slice.call(arguments, 1));
                }
                catch (err) {
                    return null;
                }
            };
        }
        catch (e) {
            bc.utils.error(e);
        }
    });
})(_bcq, pulse.rt);

// extendedInterpreter.js
(function (bc, mp) {
    'use strict';

    var mappingLangFuncs = {
        readLocalStorage: function (key) {
            return bc.store.read(key, 'localStorage');
        },
        writeLocalStorage: function (key, val) {
            return bc.store.write(key, val, 'localStorage');
        },
        readSessionStorage: function (key) {
            return bc.store.read(key, 'sessionStorage');
        },
        writeSessionStorage: function (key, val, expires) {
            return bc.store.write(key, val, 'sessionStorage');
        },
        getExpiryTime: function (cookie, expTime, prop) {
            var maxTime = expTime;
            if (prop && cookie.indexOf(';') === -1 && cookie.indexOf(prop) > -1) {
                return maxTime;
            }
            if (cookie && cookie.indexOf('|') > -1) {
                var ckList = cookie.split(';');
                ckList.forEach(function (cks) {
                    var expTime = parseInt(cks.trim().split('|')[1], 10);
                    maxTime = Math.max(expTime, maxTime);
                });
            }
            return maxTime;
        },
        setCookie: function (name, newValue, property, decode, encode, expirationTime) {
            if(name === undefined || name === null){
                return null;
            }
            newValue = newValue || null;
            var NON_EXPIRY_PROPERTY_LIST = ['s_sess_2', 's_pers_2'],
                SEPARATOR = ';',
                EQUAL = '=',
                PIPE = '|';
            var setCookie = function (name, value, domain, path, expires, secure) {
                var options = {
                    domain: domain,
                    path: path,
                    expires: expires,
                    setExpire: (expires !== undefined && expires !== new Date().getTime() && NON_EXPIRY_PROPERTY_LIST.indexOf(name) === -1) ? true : false,
                    secure: secure
                };
                bc.store.setCookie(name, value, options);
            };
            var ckExpiryTime = mp.getExpiryTime(decodeURIComponent(bc.store.getCookie(name)), expirationTime, property);
            decode = decode || false;
            var args = arguments;
            var ckObj = {},
                ckArray = [],
                ckAfterChange,
                propertyExists = false,
                key,
                newValueEncoding,
                cookie = bc.store.getCookie(name) || '';
            if (decode) {
                var decodedckArray = decodeURIComponent(cookie).split(SEPARATOR);
                propertyExists = false;
                for (var i = 0; i < decodedckArray.length; i++) {
                    if (decodedckArray[i].trim().length) {
                        key = decodedckArray[i].split(EQUAL)[0].trim();
                        if (key === property) {
                            propertyExists = true;
                            if (newValue === 'delete') {
                                decodedckArray.splice(i, 1);
                            }
                            else {
                                newValueEncoding = encode ? encodeURIComponent(newValue) : newValue;
                                decodedckArray[i] = NON_EXPIRY_PROPERTY_LIST.indexOf(name) > -1 ? decodedckArray[i].split(EQUAL)[0] + EQUAL + newValueEncoding : decodedckArray[i].split(EQUAL)[0] + EQUAL + newValueEncoding + PIPE + expirationTime;
                            }
                            break;
                        }
                    }
                }
                if (!propertyExists) {
                    newValueEncoding = encode ? encodeURIComponent(newValue) : newValue;
                    var cookieStr = NON_EXPIRY_PROPERTY_LIST.indexOf(name) > -1 ? property + EQUAL + newValueEncoding : property + EQUAL + newValueEncoding + PIPE + expirationTime;
                    decodedckArray.push(cookieStr.trim());
                }
                var decodedCkStr = decodedckArray.join(SEPARATOR);
                var decodedckList = decodedCkStr.charAt(0) === SEPARATOR ? decodedCkStr.slice(1) : decodedCkStr;
                decodedckList = decodedckList.replace(/;/g, '; ');
                ckAfterChange = encodeURIComponent(decodedckList);
                setCookie(name, ckAfterChange, "walmart.com", "/", ckExpiryTime);
            }
            else {
                switch (args.length) {
                    case 3:
                        ckArray = cookie.split(SEPARATOR);
                        propertyExists = false;
                        for (var j = 0; j < ckArray.length; j++) {
                            key = ckArray[j].split(EQUAL)[0].trim();
                            if (key === property) {
                                propertyExists = true;
                                if (newValue === 'delete') {
                                    ckArray.splice(j, 1);
                                }
                                else {
                                    ckArray[j] = ckArray[j].split(EQUAL)[0] + EQUAL + newValue;
                                }
                            }
                        }
                        if (!propertyExists) {
                            ckArray.push(property + EQUAL + newValue);
                        }
                        ckAfterChange = ckArray.join(SEPARATOR);
                        setCookie(name, ckAfterChange, "walmart.com", "/", ckExpiryTime);
                        break;
                    default:
                        setCookie(name, newValue, "walmart.com", "/", ckExpiryTime);
                }
            }
        },
        getCookie: function (name, property, decode, index) {
            if(name === undefined || name === null){
                return null;
            }
            var SEPARATOR = ';',
                EQUAL = '=',
                PIPE = '|',
                args = arguments,
                decodedckArray = [],
                ckList = [],
                decodedckObj = {},
                propertyArray = [],
                cookieObj = {},
                expTime = new Date().getTime(),
                nonExpiredCookies = [],
                cookieList = [],
                options,
                NON_EXPIRY_PROPERTY_LIST = ['s_sess_2', 's_pers_2'];
            decode = decode || false;
            var setCookie = function (name, expTime, nonExpiredCookies) {
                var options = {
                    domain: "walmart.com",
                    path: "/",
                    expires: expTime,
                    setExpire: NON_EXPIRY_PROPERTY_LIST.indexOf(name) === -1 ? true : false
                };
                // Delete old cookie
                var decodedCookieList = nonExpiredCookies.join(SEPARATOR).charAt(0) === SEPARATOR ? nonExpiredCookies.join(SEPARATOR).slice(1) : nonExpiredCookies.join(SEPARATOR);
                var cookieAfterChange = encodeURIComponent(decodedCookieList);
                bc.store.setCookie(name, cookieAfterChange, options);
            };
            if (decode) {
                var ck = bc.store.getCookie(name);
                if (!ck) {
                    return null;
                }
                else {
                    decodedckArray = decodeURIComponent(ck).split(SEPARATOR);
                    for (var i = 0; i < decodedckArray.length; i++) {
                        var decodedckArrContents = decodedckArray[i].split(EQUAL);
                        var ckKey = decodedckArrContents[0].trim(),
                            ckValue = decodedckArrContents[1];
                        if (ckValue) {
                            var time = parseInt(ckValue.split(PIPE)[1], 10);
                            if (time > new Date().getTime()) {
                                decodedckObj[ckKey] = ckValue;
                                nonExpiredCookies.push(decodedckArray[i]);
                            }
                        }
                    }
                    if (decodedckObj[property]) {
                        propertyArray = decodedckObj[property].split(PIPE);
                        cookieObj = index !== undefined ? decodeURIComponent(propertyArray[index]) : decodeURIComponent(propertyArray);
                    }
                    else {
                        cookieObj = null;
                    }
                    if (decodedckArray[0] === 'null' || decodedckArray[0] === 'undefined') {
                        decodedckArray = [];
                    }
                    // update cookies before returning result
                    if (nonExpiredCookies.length || decodedckArray.length) {
                        expTime = mp.getExpiryTime(decodeURIComponent(bc.store.getCookie(name)), parseInt(decodedckArray[0].split(PIPE)[1], 10));
                    }
                    setCookie(name, expTime, nonExpiredCookies);
                    return cookieObj || null;
                }
            }
            else {
                cookieObj = bc.store.getCookie(name) || null;
                cookieObj = decodeURIComponent(cookieObj);
                if (cookieObj) {
                    // Send only non expireed cookies. Remove the expired ones
                    ckList = cookieObj.trim().split(SEPARATOR);
                    for (var i = 0; i < ckList.length; i++) {
                        ckList[i] = ckList[i].trim();
                        if (ckList[i].indexOf(EQUAL) !== -1) {
                            var ckContents = ckList[i].split(EQUAL);
                            var ckKey = ckContents[0],
                                ckValue = ckContents[1];
                            if (ckValue && ckValue.indexOf(PIPE) !== -1) {
                                var time = parseInt(ckValue.split(PIPE)[1], 10);
                                if (time > new Date().getTime()) {
                                    nonExpiredCookies.push(ckList[i]);
                                }
                            }
                            // cookies without a timeStamp are to be added as well
                            if (ckValue && ckValue.indexOf(PIPE) === -1) {
                                nonExpiredCookies.push(ckList[i]);
                            }
                        }
                    }
                    if (nonExpiredCookies.length || ckList.length) {
                        expTime = mp.getExpiryTime(decodeURIComponent(bc.store.getCookie(name)), parseInt(ckList[0].split(PIPE)[1], 10));
                    }
                    setCookie(name, expTime, nonExpiredCookies);
                    cookieObj = bc.store.getCookie(name);
                }
            }
            return cookieObj;
        },
        template: function () {
            var args = arguments || [];
            var template = args[0];

            if (typeof template === 'string') {
                for (var i = 1; i < args.length; i++) {
                    var value = args[i];
                    var replacePattern = new RegExp('{{s' + i + '}}', 'g');
                    template = template.replace(replacePattern, value);
                }
            }
            return template;
        },
        switchCase: function () {
            if (arguments && arguments.length >= 3) {
                var args = Array.prototype.slice.call(arguments),
                    len = args.length,
                    defaultValue
                if (len % 2 === 0) {
                    defaultValue = args.pop();
                }
                for (var i = 1; i < len; i = i + 2) {
                    if (args[0] === args[i]) {
                        return args[i + 1];
                    }
                }
                return defaultValue;
            }
            return null;
        },
        comparison: function () {
            if (arguments && arguments.length >= 3) {
                var operatorList = ["==", "===", "!=", "!==", "<", "<=", ">", ">="],
                    args = Array.prototype.slice.call(arguments) || [],
                    operator = args[0],
                    param1 = args[1],
                    param2 = args[2],
                    result = false;
                if (operatorList.indexOf(operator) === -1) {
                    return null;
                }
                switch (operator) {
                    case "==": result = param1 == param2; break;
                    case "===": result = param1 === param2; break;
                    case "!=": result = param1 != param2; break;
                    case "!==": result = param1 !== param2; break;
                    case "<": result = param1 < param2; break;
                    case "<=": result = param1 <= param2; break;
                    case ">": result = param1 > param2; break;
                    case ">=": result = param1 >= param2; break;
                }
                return result;
            }
            return null;
        },
        isNull: function () {
            if (arguments && arguments.length > 0) {
                var args = Array.prototype.slice.call(arguments) || [];
                return (args[0] === null);
            }
            return null;
        },
        hasValue: function () {
            if (arguments && arguments.length > 0) {
                var args = Array.prototype.slice.call(arguments) || [];
                return (typeof args[0] !== 'undefined' && args[0] !== null);
            }
            return null;
        },
        logicalOperations:  function(opArr){
            if(opArr === null || typeof(opArr) !== 'object'){
                return null;
            }
            var evaluate = function(obj){
                var key = Object.keys(obj)[0];
                if(key === 'OR'){
                    return obj[key].some(function(param){
                        return typeof(param) === 'object' ? evaluate(param) : param;
                    });
                }
                else if(key === 'AND'){
                    return obj[key].every(function(param){
                        return typeof(param) === 'object' ? evaluate(param): param;
                    });
                }
            };
            return evaluate(opArr);
        },
        queryURLString: function(URLString, queryParam) {
            var indexQueryParams = URLString.indexOf("?") + 1;
            var queryParamStr = URLString.substr(indexQueryParams);
            var queryParams = queryParamStr.split("&");
            var responseObj = {};

            for (var i = 0; i < queryParams.length; ++i) {
                var paramValue = queryParams[i].split("=");
                var param = paramValue[0];
                var value = paramValue[1];
                responseObj[param] = value;
            }

            if (queryParam) {
                return responseObj[queryParam];
            } else {
                return responseObj;
            }
        }
    };

    [
        "readLocalStorage",
        "writeLocalStorage",
        "readSessionStorage",
        "writeSessionStorage",
        "getExpiryTime",
        "setCookie",
        "getCookie",
        "template",
        "switchCase",
        "comparison",
        "isNull",
        "hasValue",
        "logicalOperations",
        "queryURLString"
    ].forEach(function (method) {
        try {
            mp[method] = function () {
                try {
                    return mappingLangFuncs[method].apply(undefined, arguments);
                }
                catch (err) {
                    return null;
                }
            };
        }
        catch (e) {
            bc.utils.error(e);
        }
    });
})(_bcq, pulse.rt);

(function (bc) {
    'use strict';

    bc.abstract = {
        setReferrer: function (params) {
            var params = params || {}
            var tmp = {
                r: params.r || bc.utils.referrer || bc.utils.getReferrerUrl(),
                ref: document.referrer || ""
            };
            return bc.utils.merge(params, tmp);
        },
        metadata: function (params, ctx, act, name) {
            // All the attribute which are duplicated with same value will be removed in some time.
            var params = params || {},
                opt = this.options || {},
                wd = window.document || {},
                topics = bc.options.topics;
            params.cd = params.cd || {};
            params.cd.dim = bc.utils.clientDim();	//include client Details
            if (topics) {
                params.topics = topics;
            }
            var contextInfo = bc.utils.getContextInfo() || {};
            var appVersion = undefined;
            var dataCenter = undefined;
            try {
              appVersion = contextInfo.appVersion
              dataCenter = contextInfo.dataCenter
            } catch (e) { }
            var tmp = {
                ts: params.ts || new Date().getTime(), 					// Timestamp that's needed to add as a "random" parameter to avoid url caching
                pv_id: bc.page_view_id, 								// Add the Page View ID to the call
                bn: bc.utils.rumSeq,
                act: act,
                ctx: ctx,
                name: name,
                u: params.u || wd.URL,				 	// use URL instead of location.href because of a Safari bug
                la: wd.documentElement && wd.documentElement.lang ? wd.documentElement.lang : "",
                aid: opt.site_id,
                an: opt.site_version,
                av: opt.tm_version,
                opv_id: bc.original_page_view_id,
                sv: bc.options.sv || "0.0.0",
                _apv: appVersion || "unknown",
                _dc: dataCenter || "unknown"
            };
            (tmp && tmp.sv === "0.0.0") ? tmp.si = opt.site_id : null;
            (opt && opt.subAppId && opt.subAppId !== "") ? tmp.said = opt.subAppId : null;
            (opt && opt.marketId && opt.marketId !== "") ? tmp.mrk = opt.marketId : null;
            (opt && opt.martId && opt.martId !== "") ? tmp.mrt = opt.martId : null;
            bc.options.tid ? tmp.tid = bc.options.tid : null;
            return bc.utils.merge(params, tmp);
        },
        formatParams: function (params) {
            var val = {},
                replacer = function (name, val) {
                    return (val || val==0) ? val : "";
                }
            for (var k in params || {}) {
                val[k] = (params[k] && typeof params[k] === 'object') ? JSON.stringify(params[k], replacer) : params[k];
            }
            return val;
        }
    }
})(_bcq);

(function (bc) {
	'use strict';

	bc.handlers.wmbeacon = {
		/**
		 * Initialize function for the WMBeacon Handler
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} Info Object about the configuration object for the Partner's Library and the Partner Mappings at the Partner Level
		 * @return {void}
		 */
		initialize: function (info) {
			this.options = info.opts;
			this.beacon_url = bc.domain + "rum.gif";
			this.tap_redirect_url = bc.domain + "rum.gif";
			// this.tap_redirect_url = bc.domain + "pm.gif";
		},
		/**
		 * @desc Placeholder for the "tagAction" function of the Partner Handlers
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {String} ctx the identifier of the context for the action (where the action took place)  
		 * @param {String} act Name of the Action to be tagged.
		 * @param {String} name Name of the ReportID for filtering.
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} pn Mapping partner name
		 * @return {Int} whether the action was tagged or not (0||1)
		 */

		tagAction: function (ctx, act, name, attrs, pn) {
			var mappingsOutput = bc.mappingsExecuter.executeMapping ? bc.mappingsExecuter.executeMapping(ctx, act, attrs, pn) || {} : {};
			var params = bc.utils.getParams(attrs, mappingsOutput, true) || {};
			params = this.metadata(params, ctx, act, name);
			var nonSnActions = ['performanceMetrics', 'performanceMetric', 'ads', 'log', 'metric'];
			bc.utils.getReferralPvId ? params.rpv_id = bc.utils.getReferralPvId(params.pv_id) : "";
			if (nonSnActions.indexOf(params.act) === -1) {
				bc.utils.getSeqNum ? params.sn = bc.utils.getSeqNum() : "";
			}
			var batchName = undefined;
			if(act === "moduleView" && params && params.sn === 1){
				batchName = undefined;
			}else{
				batchName = bc.batchUtils.getBatchFlag(act);
			}
			batchName && bc.batchIntervalFuns[batchName] ? this.processBatchActions(this.beacon_url, params, batchName) : this.triggerUrl(this.beacon_url, params);
			if (act === "pageView") {
				this.sendTapRedirectRequest(this.tap_redirect_url);
			}
			return 1;
		},
		triggerUrl: function (baseURL, params) {
			var params = this.formatParams(params),
				urlQS = bc.utils.urlSerialize(params);
			try {
				urlQS = "hc=" + Math.abs(bc.utils.hashCode(urlQS)) + "&" + urlQS;
			}
			catch (e) {
				bc.utils.error("ERROR: In setting up hashcode");
				bc.utils.error(e);
			}
			this.sendRequest(baseURL, urlQS);
		},
		sendTapRedirectRequest: function (tapRedirectUrl) {
			var img = new Image();
			img = bc.utils.updateReferrerPolicy(img);
			img.src = tapRedirectUrl + '?param=PAM';
			// navigator.sendBeacon && navigator.sendBeacon(tapRedirectUrl, "");
		},
		sendRequest: function (baseURL, urlQS) {
			var xhr, img;
			/**
			 * If browser supports sendBeacon navigator.sendBeacon, then we will try
			 * to queue the request to browser so thet it is not lost when we go to the new page or else it will foloow the xhr it img process.
			 * If navigator.sendBeacon fails, it will got for normal approach of xhr or img.
			 */
			var useSendBeacon = (_bcq && _bcq.options && _bcq.options.useSendBeacon === false) ? false : true;
			if (useSendBeacon && navigator.sendBeacon && navigator.sendBeacon(baseURL, urlQS + "&sbc=true") === true) {
				return true;
			}
			xhr = bc.utils.corsReq('post', baseURL);
			if (xhr && xhr.send) {	// Trigger cors post request if supported
				setTimeout(function () {
					try {
						xhr.send(urlQS);
					} catch (err) {
						throw err;
					}
				}, 0);
			} else {
				img = new Image();
				img = bc.utils.updateReferrerPolicy(img);
				img.src = baseURL + ((baseURL.indexOf('?') > -1) ? '&' : '?') + urlQS;
			}
		},
		processBatchActions: function (baseURL, params, batchName) {
			delete params.aid;
			delete params.si;
			delete params.an;
			delete params.av;
			delete params.sv;
			var formattedParams = this.formatParams(params);
			var urlQS = bc.utils.urlSerialize(formattedParams);
			try {
				params.hc = Math.abs(bc.utils.hashCode(urlQS));
			}
			catch (e) {
				bc.utils.error("ERROR: In setting up hashcode");
				bc.utils.error(e);
			}
			if (bc && bc.options && bc.options.bConf && bc.options.bConf[batchName]) {
				// 1. setInterval
				// 2. bmc - Batch Max Count
				// 3. bbs - Batch Byte Size
				var existingList = bc.batchUtils.readBatchEvtFromStorage() || {};
				var batchData = existingList[batchName] || {};
				var listToProcess = batchData.reqList || [];
				var listByteSize = batchData.reqListByteSize || 0;
				listToProcess.push(params);
				listByteSize = listByteSize + bc.batchUtils.getQsByteSize(urlQS);
				var curBatch = bc.options.bConf[batchName];
				var bmc = curBatch.bmc || bc.options.default_batch_batchMaxCount;
				var bbs = curBatch.bbs || bc.options.default_batch_batchByteSize;
				if (listToProcess.length === bmc) {
					// triger the batch
					bc.utils.log("We should send the batch now as the list size has reached for" + batchName + "with");
					bc.utils.log(listToProcess);
					this.triggerBatch(batchName, listToProcess);
				} else if (listByteSize >= bbs) {
					bc.utils.log("We should send the batch now as the character length has reached for" + batchName + "with");
					bc.utils.log(listToProcess);
					this.triggerBatch(batchName, listToProcess);
				} else {
					bc.utils.log("We should save the request to sessionstorage for" + batchName + "with");
					bc.utils.log(params);
					bc.batchUtils.writeBatchEvtToStorage(batchName, listToProcess, listByteSize);
				}
			}
		},
		triggerBatch: function (batchName, listToProcess, isFromLastSession) {
			var opt = this.options || {};
			var rec = {
				bsn: bc.batchUtils.getBatchSeqNum(),
				bts: new Date().getTime(),
				oldBatch: isFromLastSession === true ? true : false,
				bpvId: bc.page_view_id,
				el: listToProcess,
				aid: opt.site_id,
				an: opt.site_version,
				av: opt.tm_version,
				sv: bc.options.sv || "0.0.0",
			}
			rec = this.formatParams(rec);
			var urlQS = bc.utils.urlSerialize(rec);
			try {
				urlQS = "bhc=" + Math.abs(bc.utils.hashCode(urlQS)) + "&" + urlQS;
			}
			catch (e) {
				bc.utils.error("ERROR: In setting up hashcode");
				bc.utils.error(e);
			}
			this.sendRequest(this.beacon_url, urlQS);
			bc.batchUtils.writeBatchEvtToStorage(batchName, undefined);
		},
		// Add the visibilitychange event to clean up the local storage
		visibilityEvtFun: function () {
			try {
				var wmbeaconHandler = bc.handlers["wmbeacon"];
				if (document.visibilityState === 'hidden' && wmbeaconHandler && wmbeaconHandler.clearBatchInterval) {
					bc.utils.log("Visibility hidden event fired");
					wmbeaconHandler.clearPendingBatchData(false)
				}
			} catch (e) {
				bc.utils.log("ERROR: could not complete visibilityEvtFun");
				bc.utils.log(e);
			}
		},
		/**
		 * This method creates a number of setIntervals based on the number of batches set from fornt end.
		 * set batch interval functions
		 * This will first flush out existing pending data
		 * Then cleal all the existing batch functions
		 * Set ne batch functions
		 * set visibilitychange event also to flush data when user mves out of the page or close it.
		*/
		setBatchInterval: function (onPageLoad) {
			try {
				var thisObj = this;
				if (bc && bc.options && bc.options.bConf && Object.keys(bc.options.bConf).length > 0) {
					// Flush all the pending batch data && Clear all the existing batch interval functions before setting new ones.
					thisObj.clearBatchInterval(onPageLoad);
					// Set new batch interval functions
					var bConf = bc.options.bConf;
					var batchNames = Object.keys(bConf);
					var totalBatches = batchNames.length;
					for (var count = 0; count < totalBatches; count++) {
						var eachBatchName = batchNames[count];
						var eachBatchCong = bConf[eachBatchName];
						if (eachBatchName && eachBatchCong) {
							(function (bName, bCong) {
								bc.batchIntervalFuns[bName] = setInterval(function () {
									var existingList = bc.batchUtils.readBatchEvtFromStorage() || {};
									var batchData = existingList[bName] || {};
									var listToProcess = batchData.reqList || [];
									bc.utils.log("Ready to push the batch for" + bName + "with setInteval");
									bc.utils.log(listToProcess);
									if (listToProcess && listToProcess.length > 0) {
										thisObj.triggerBatch(bName, listToProcess);
									}
								}, bCong.bi || bc.options.default_batch_interval);
							})(eachBatchName, eachBatchCong);
						}
					}
					// Remove the listner first if already existing and then add a new one
					document.removeEventListener('visibilitychange', thisObj.visibilityEvtFun, false);
					document.addEventListener('visibilitychange', thisObj.visibilityEvtFun, false);
				}
			}
			catch (e) {
				bc.utils.error("ERROR: in setBatchInterval");
				bc.utils.error(e);
			}
		},
		clearBatchInterval: function (onPageLoad) {
			try {
				// Flush all the pending batch data
				onPageLoad ? this.clearPendingBatchData(true) : this.clearPendingBatchData(false);
				// Clear all the existing batch interval functions before setting new ones.
				var batchFuns = bc.batchIntervalFuns || {};
				var existingBatches = Object.keys(batchFuns);
				for (var check = 0; check < existingBatches.length; check++) {
					clearInterval(batchFuns[existingBatches[check]]);
				}
				bc.batchIntervalFuns = {};
				// Remove the listners
				document.removeEventListener('visibilitychange', this.visibilityEvtFun, false);
			}
			catch (e) {
				bc.utils.error("ERROR: in clearBatchInterval");
				bc.utils.error(e);
			}
		},
		clearPendingBatchData: function (isFromLastSession) { // True-> Previous Session, False-> Current Session
			try {
			var existingList = bc.batchUtils.readBatchEvtFromStorage() || {};
			var batchNames = Object.keys(existingList);
			var totalBatches = batchNames.length;
			for (var count = 0; count < totalBatches; count++) {
				var batchName = batchNames[count];
				var batchData = existingList[batchName] || {};
				var listToProcess = batchData.reqList || [];
				bc.utils.log("Ready to push the batch for" + batchName + "with for previous session as " + isFromLastSession);
				bc.utils.log(listToProcess);
				if (listToProcess && listToProcess.length > 0) {
					this.triggerBatch(batchName, listToProcess, isFromLastSession);
				}
			}
			} catch (e) {
				bc.utils.log("ERROR: in clearPendingBatchData");
				bc.utils.log(e);
			}
		}
	};
	bc.handlers.wmbeacon = bc.utils.merge({}, bc.abstract, bc.handlers.wmbeacon);
})(_bcq);
(function(bc) {
    'use strict';
    bc.options = bc.options || {};
    var mf = {};
		
mf['rum-mappings.debug.js'] = 'M1iNbWzfwvk2+u3a0H9_IZXqrW0='
mf['rum-mappings.js'] = '45ONZKZzQJyeNF9pVDcsCCRvEdc='
    bc.options["mappings_files"] = mf;
})(_bcq);

/**
 * @desc Loads and initialize the Partner's libraries we need to deploy
 * @author Carlos Soto <csoto@walmartlabs.com>
 * @param {Object} Configuration data about the Partners
 * @return void
 */

(function (bc, config) {
	'use strict';
	bc.pulse_lsck = bc.pulse_lsck || undefined; // This prop hold if any sharding cookie set through lua.
	bc.loadQM = bc.loadQM || true; // This prop whether QM active for the current session or not.
	bc.batchIntervalFuns = bc.batchIntervalFuns || {};
	bc.options.default_batch_interval = 10000; // 20 Sec
	bc.options.default_batch_batchMaxCount = 10;  // Max number of events in a batch
	bc.options.default_batch_batchByteSize = 700000; // Max number of bytes in a batch (700 KB)
	bc.options.default_bConf = {
		b1: {
			bacts: ['performanceMetrics', 'performanceMetric', 'ads', 'log', 'metric', 'moduleView'],
			bi: 10000, // batchInterval = 10 Sec
			bmc: 10, // batchMaxCount = Max number of events in a batch
			bbs: 700000 // batchByteSize = Max number of characters in a batch (700 KB)
		}
	};
	var cdnHost = 'https://b.wal.co/',
		host = bc.domain,
		rum_mapping_url = "rum-mappings",
		partner = "wmbeacon",
		wmbeaconHandler = bc.handlers[partner];
	// Read the pulse load shredding cookie at the starting. It will update bc.pulse_lsck global value.
	bc.utils.readPulseConfigCookie();
	// Initialize the wmbeacon handler
	wmbeaconHandler ? wmbeaconHandler.initialize(config.ptns[partner], config) : null;
	// Set/Reset batching based on config
	bc.utils.setResetBatching();
	bc.utils.setGlobalSodPref ? bc.utils.setGlobalSodPref(config) : null;
	bc.utils.getTopics ? bc.utils.getTopics() : null;
	// Load qm library from cdn. This will check all the necessary conditions whether to load qm session or not.
	bc.qmUtils && bc.qmUtils.loadQmFromCDN ? bc.qmUtils.loadQmFromCDN() : null;
	// Load the mapping file rum-mappings.js
	rum_mapping_url = bc.options.mode === 'debug' ? rum_mapping_url + '.debug.js' : rum_mapping_url + '.js';
	if (bc.options["mappings_files"] && bc.options["mappings_files"][rum_mapping_url]) {
		rum_mapping_url = rum_mapping_url + ';' + bc.options["mappings_files"][rum_mapping_url];
	}
	rum_mapping_url += '?' + bc.utils.urlSerialize({ bh: bc.options.bh });
	host.indexOf("beacon.walmart.com") !== -1 ? host = cdnHost : null;
	// Load the rum-mappings files
	bc.utils.loadScript(host + rum_mapping_url);
	// Run all of the commands in the queue
	bc.push.apply(bc, bc.queue);
	// Read the pulse shredding cookie in an interval of 2 mins.
	// If the cookie exists on the page load, then set the timer. 
	// This means if we don't get the cookie at the page load, then there won't be any effect if the cookie comes later.
	// bc.pulse_lsck ? bc.utils.runCookieTimer() : null;
})(_bcq, _bcc);
