'use strict';
/**
* Opt in (e.g. EU):
* default all scripts disabled.
* cookie banner
*
* Opt out (e.g. US):
* default all scripts enabled
* opt out cookie banner
*
* Other regions:
* default all scripts enabled
* no banner
*
*
* For examples to edit the behaviour of the banner, please see https://github.com/really-Simple-Plugins/complianz-integrations
* */

jQuery(document).ready(function ($) {
	//prevent caching of the WP Rest API by varnish or other caching tools
	complianz.url = complianz.url + '&token='+Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);

	/**
	 * CustomEvent() polyfill
	 * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
	 */
	(function () {
		if (typeof window.CustomEvent === 'function') return false;
		function CustomEvent(event, params) {
			params = params || { bubbles: false, cancelable: false, detail: undefined };
			var evt = document.createEvent('CustomEvent');
			evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
			return evt;
		}
		CustomEvent.prototype = window.Event.prototype;
		window.CustomEvent = CustomEvent;
	})();

	var banner;//look this one up when the cookiebanner loads.
	var banner_container = $('#cmplz-cookiebanner-container');
	var manage_consent_button;
	var waiting_inline_scripts = [];
	var waiting_scripts = [];
	var placeholder_class_index = 0;
	var all_scripts_hook_fired = false;
	var enabled_categories = [];
	var categories = [
		'functional',
		'preferences',
		'statistics',
		'marketing',
	];

	/**
	 * Get a cookie by name
	 * @param name
	 * @returns {string}
	 */

	window.cmplz_get_cookie = function(name) {
		if (typeof document === 'undefined') {
			return '';
		}
		name = complianz.prefix+name + "=";
		var cArr = document.cookie.split(';');
		for (var i = 0; i < cArr.length; i++) {
			var c = cArr[i].trim();
			if (c.indexOf(name) == 0)
				return c.substring(name.length, c.length);
		}

		return "";
	}

	/**
	 * set a cookie
	 * @param name
	 * @param value
	 * @param days
	 */

	window.cmplz_set_cookie = function(name, value) {
		if (typeof document === 'undefined') {
			return;
		}
		var secure = ";secure";
		var date = new Date();
		date.setTime(date.getTime() + (complianz.cookie_expiry * 24 * 60 * 60 * 1000));
		var expires = ";expires=" + date.toGMTString();

		if (window.location.protocol !== "https:") secure = '';

		var domain = cmplz_get_cookie_domain();
		if (domain.length > 0) {
			domain = ";domain=" + domain;
		}
		var prefix = '';
		//the usprivacy cookie should not get a prefix
		if (name.indexOf('usprivacy') === -1) {
			prefix = complianz.prefix;
		}
		document.cookie = prefix+name + "=" + value + ";SameSite=Lax" + secure + expires + domain + ";path="+cmplz_get_cookie_path();
	}

	/**
	 * Check if needle occurs in the haystack
	 * @param needle
	 * @param haystack
	 * @returns {boolean}
	 */
	window.cmplz_in_array = function(needle, haystack) {
		var length = haystack.length;
		for(var i = 0; i < length; i++) {
			if(haystack[i] == needle) return true;
		}
		return false;
	}

	/**
	 * Show manage consent area
	 * This way we make sure the "no javascript" message is shown when javascript is not active
	 */
	$('#cmplz-manage-consent-container-nojavascript').hide();
	$('#cmplz-manage-consent-container').show();

	/**
	 * Sets all accepted categories as class in body
	 */

	function set_category_as_body_class() {
		var classList = document.body.className.split(/\s+/);
		for (var i = 0; i < classList.length; i++) {
			if ( classList[i].indexOf('cmplz_') !== -1 ) {
				document.body.classList.remove( classList[i] );
			}
		}
		var cats = cmplz_accepted_categories();
		for (var i in cats) {
			document.body.classList.add('cmplz_'+cats[i]);
		}
		document.body.classList.add('cmplz-' + complianz.region);
		document.body.classList.add('cmplz-' + complianz.consenttype);
	}

	/**
	 * Set placeholder image as background on the parent div, set notice, and handle height.
	 *
	 * */

	function set_blocked_content_container() {
		//to prevent this function to twice on an element, we add an attribute to each element that has been processed.
		//then skip elements with that element.

		$('.cmplz-image').each(function (i, obj) {
			if ( $(this).hasClass('cmplz-processed') ) return;
			$(this).addClass('cmplz-processed' );
			var blocked_image_container = $(this).parent();
			blocked_image_container.addClass('cmplz-blocked-content-container');
			//handle browser native lazy load feature
			if ($(this).attr('loading') === 'lazy' ) {
				$(this).removeAttr('loading');
				$(this).data('deferlazy', 1);
			}
			//insert placeholder text
			if (!cmplz_has_consent('marketing') && !blocked_image_container.find(".cmplz-blocked-content-notice").length) {
				var placeholderText = complianz.placeholdertext;
				if (typeof placeholderText !== 'undefined') blocked_image_container.append('<button class="cmplz-blocked-content-notice cmplz-accept-marketing">' + placeholderText + '</button>');
			}
		});


		$('.cmplz-placeholder-element').each(function () {
			if ( $(this).hasClass('cmplz-processed') ) return;
			$(this).addClass('cmplz-processed' );

 			//we set this element as container with placeholder image
			var blocked_content_container;
			var service = $(this).data('service');
			if ($(this).hasClass('cmplz-iframe')) {

				//handle browser native lazy load feature
				if ($(this).attr('loading') === 'lazy' ) {
					$(this).removeAttr('loading');
					$(this).data('deferlazy', 1);
				}

				blocked_content_container = $(this).parent();
			} else {
				blocked_content_container = $(this);
			}
			var curIndex = blocked_content_container.data('placeholder_class_index');
			//if the blocked content container class is already added, don't add it again
			if (typeof curIndex === 'undefined') {
				placeholder_class_index++;
				blocked_content_container.addClass('cmplz-placeholder-' + placeholder_class_index);
				blocked_content_container.addClass('cmplz-blocked-content-container');
				blocked_content_container.data('placeholder_class_index', placeholder_class_index);
				//insert placeholder text
				if ( !cmplz_has_consent('marketing') && !blocked_content_container.find(".cmplz-blocked-content-notice").length) {
					var placeholderText = complianz.placeholdertext;
					if (typeof placeholderText !== 'undefined') {
						blocked_content_container.append('<button aria-label="'+service+'" class="cmplz-blocked-content-notice cmplz-accept-marketing" data-service="'+service+'">' + placeholderText + '</button>');
					}
				}

				//handle image size for video
				var src = $(this).data('placeholder-image');
				if (typeof src !== 'undefined' && src.length) {
					src = src.replace('url(', '').replace(')', '').replace(/\"/gi, "");
					$('head').append('<style>.cmplz-placeholder-' + placeholder_class_index + ' {background-image: url(' + src + ') !important;}</style>');
					set_blocked_content_container_aspect_ratio($(this), src, placeholder_class_index);
				}
			}
		});

		/**
		 * In some cases, like ajax loaded content, the placeholders are initialized again. In that case, the scripts may need to be fired again as well.
		 * We're assuming that statistics scripts won't be loaded with ajax, so we only load marketing level scripts
		 *
		 */
		if ( cmplz_has_consent('marketing') ) {
			cmplz_enable_category('marketing');
		}

	}

	/**
	 * Set the height of an image relative to the width, depending on the image widht/height aspect ratio.
	 *
	 *
	 * */

	function set_blocked_content_container_aspect_ratio(container, src, placeholder_class_index) {
		if (typeof container === 'undefined') return;

		//we set the first parent div as container with placeholder image
		var blocked_content_container = container.parent();

		//handle image size for video
		var img = new Image();
		img.addEventListener("load", function () {
			var imgWidth = this.naturalWidth;
			var imgHeight = this.naturalHeight;

			//prevent division by zero.
			if (imgWidth === 0) imgWidth = 1;
			var w = blocked_content_container.width();
			var h = imgHeight * (w / imgWidth);

			var heightCSS = '';
			if (src.indexOf('placeholder.jpg') === -1) {
				heightCSS = 'height:' + h + 'px;';
			}

			$('head').append('<style>.cmplz-placeholder-' + placeholder_class_index + ' {' + heightCSS + '}</style>');
		});
		img.src = src;
	}

	/**
	 * Keep window aspect ratio in sync when window resizes
	 * To lower the number of times this code is executed, it is done with a timeout.
	 *
	 * */

	var resizeTimer;
	$(window).on( "resize", function() {
		clearTimeout(resizeTimer);
		resizeTimer = setTimeout( set_blocked_content_container, 500);
	});

	/**
	 * 	we run this function also on an interval, because with ajax loaded content, the placeholders would otherwise not be handled.
	 */
	if ( complianz.block_ajax_content == 1 ) {
		setInterval(function () {
			set_blocked_content_container();
		}, 2000);
	}

	/**
	 * Enable scripts that were blocked
	 *
	 * */

	function cmplz_enable_category(category, service) {
		service = typeof service !== 'undefined' ? service : 'nomatch';
		if ( category === '' ) category = 'nomatch';

		if (!enabled_categories.hasOwnProperty(category)) {
			enabled_categories[category] = false;
		}

		//never run twice
		if (enabled_categories[category] ) {
            return;
		}

		//enable cookies for integrations
		if ( category === 'marketing' ) {
			cmplz_set_integrations_cookies();
		}

		//remove accept cookie notice overlay
		$('.cmplz-blocked-content-notice.cmplz-'+category+', .cmplz-blocked-content-notice[data-service='+service+']').each(function () {
			$(this).remove();
		});

		$('.cmplz-'+category+', [data-service='+service+']').each(function (i, obj) {
			//if a category is activated, but this specific service is denied, skip.
			var elementService = $(this).data('service');
			if ( category !== 'nomatch' && !cmplz_has_consent(elementService)) {
				return;
			}
			//if native class is included, it isn't blocked, so will have run already
			if ($(this).hasClass('cmplz-native')) {
				return;
			}
			if ( $(this).hasClass('cmplz-activated') ) {
				return;
			}
			$(this).addClass('cmplz-activated' );

			var tagName = $(this).prop('tagName');

			if (tagName==='STYLE'){
				var src = $(this).data('href');
				$('head').append('<link rel="stylesheet" type="text/css" href="' + src + '">');
			} else if (tagName ==='IMAGE'){
                var src = $(this).data('src-cmplz');
                $(this).attr('src', src);
                //handle browser native lazy load feature
                if ($(this).data('deferlazy')) {
                    $(this).attr('loading', 'lazy');
                }
			} else if (tagName==='IFRAME'){
                var src = $(this).data('src-cmplz');
                //check if there's an autoplay value we need to pass on
                var autoplay = cmplz_get_url_parameter($(this).attr('src'), 'autoplay');
                if (autoplay === '1') src = src + '&autoplay=1';
                $(this).attr('src', src).on( 'load' , function () {
                    //fitvids integration, a.o. Beaverbuilder
                    if (typeof $(this).parent().fitVids == 'function') {
                        $(this).parent().fitVids();
                    }
                    var curElement = $(this);

                    //handle browser native lazy load feature
                    if ($(this).data('deferlazy')) {
                        $(this).attr('loading', 'lazy');
                    }

                    //we get the closest, not the parent, because a script could have inserted a div in the meantime.
                    var blocked_content_container = $(this).closest('.cmplz-blocked-content-container');
                    //now remove the added classes
                    blocked_content_container.animate({"background-image": "url('')"}, 400, function () {
                        var cssIndex = blocked_content_container.data('placeholder_class_index');
                        blocked_content_container.removeClass('cmplz-blocked-content-container');
                        blocked_content_container.removeClass('cmplz-placeholder-' + cssIndex);
                        curElement.removeClass('cmplz-iframe-styles');
                        curElement.removeClass('cmplz-iframe');

                        //in some cases the videowrap gets added to the iframe
                        curElement.removeClass('video-wrap');
                        curElement.removeClass('cmplz-hidden');
                    });
                });
			} else if ($(this).hasClass('cmplz-placeholder-element')) {
                //other services, no iframe, with placeholders
                var blocked_content_container = $(this);
                //remove the added classes
                var cssIndex = blocked_content_container.data('placeholder_class_index');
                blocked_content_container.removeClass('cmplz-blocked-content-container');
                blocked_content_container.removeClass('cmplz-placeholder-' + cssIndex);
			}
		});

		/**
		 * Let's activate the scripts
		 */

		//create list of waiting scripts
		var scriptElements = $('script.cmplz-'+category);
		scriptElements.each(function (i, obj) {
			var waitfor = $(this).data('waitfor');
			var src = $(this).attr('src');

			if (src && src.length) {
				if (typeof (waitfor) !== "undefined") {
					waiting_scripts[waitfor] = src;
				}
			} else if ($(this).text().length) {
				if (typeof (waitfor) !== "undefined") {
					waiting_inline_scripts[waitfor] = $(this);
				}
			}
		});

		//scripts: set "cmplz-script classes to type="text/javascript"
		scriptElements.each(function (i, obj) {
            if ( $(this).hasClass('cmplz-activated') ) return;
            $(this).addClass('cmplz-activated' );

			var src = $(this).attr('src');
			if (src && src.length) {
				$(this).attr('type', 'text/javascript');

				//check if this src or txt is in a waiting script. If so, skip.
				if (cmplz_is_waiting_script(waiting_scripts, src)) {
					return;
				}

				if (typeof $(this).data('post_scribe_id') !== 'undefined') {
					var psID = '#' + $(this).data('post_scribe_id');
					if ($(psID).length) {
						$(psID).html('');
						$(function () {
							postscribe(psID, '<script src=' + src + '></script>');
						});
					}
				} else {
					$.getScript(src)
						.done(function (s, Status) {
							var all_scripts_executed = true;
							//check if we have waiting scripts
							var waitingScript = cmplz_get_waiting_script(waiting_scripts, src);
							if (waitingScript) {
								all_scripts_executed = false;
								$.getScript(waitingScript).done(function (script, textStatus) {
									cmplz_run_after_all_scripts(category);
								}).fail(function (jqxhr, settings, exception) {
									console.warn("Something went wrong " + exception);
								});
							}

							var waiting_inline_script = cmplz_get_waiting_script(waiting_inline_scripts, src);
							if (waiting_inline_script) {
								all_scripts_executed = false;
								cmplz_run_inline_script(waiting_inline_script, category);
							}

							//maybe all scripts are already done
							if (all_scripts_executed) cmplz_run_after_all_scripts(category);
						})
						.fail(function (jqxhr, settings, exception) {
							console.warn("Something went wrong " + exception);
						});
				}

			} else if ($(this).text().length) {
				//check if this src or txt is in a waiting script. If so, skip.
				if (cmplz_is_waiting_script(waiting_inline_scripts, $(this).text())) {
					return;
				}
				cmplz_run_inline_script($(this), category);
			}
		});

		//fire an event so custom scripts can hook into this.
		var details = new Object();
		details.category = category;
		details.categories = cmplz_accepted_categories();
		details.region = complianz.region;
		var event = new CustomEvent('cmplz_enable_category', { detail: details });
		document.dispatchEvent(event);

		//if there are no blockable scripts at all, we still want to provide a hook
		//in most cases, this script fires too early, and won't run yet. In that
		//case it's run from the script activation callbacks.
		cmplz_run_after_all_scripts(category);
		enabled_categories[category] = true;
	}

	/**
	 * check if the passed source has a waiting script that should be executed, and return it if so.
	 * @param waiting_scripts
	 * @param src
	 * @returns {*}
	 */

	function cmplz_get_waiting_script(waiting_scripts, src) {
		for (var waitfor in waiting_scripts) {
			var waitingScript;//recaptcha/api.js, waitfor="gregaptcha"
			if (waiting_scripts.hasOwnProperty(waitfor) ) {
				waitingScript = waiting_scripts[waitfor];
				if (typeof waitingScript !== 'string') {
					waitingScript = waitingScript.text();
				}
				if (src.indexOf(waitfor) !== -1) {
					var output = waiting_scripts[waitfor];
					delete waiting_scripts[waitfor];
					return output;
				}
			}
		}

		return false;
	}

	/**
	 * Because we need a key=>value array in javascript, the .length check for an empty array doesn't work.
	 * @param arr
	 * @returns {boolean}
	 */
	function cmplz_array_is_empty(arr) {
		for (var key in arr) {
			if (arr.hasOwnProperty(key)) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Check if the passed src or script is waiting for another script and should not execute
	 * @param waiting_scripts
	 * @param srcOrScript
	 */

	function cmplz_is_waiting_script(waiting_scripts, srcOrScript) {
		for (var waitfor in waiting_scripts) {
			var waitingScript = waiting_scripts[waitfor];
			if (typeof waitingScript !== 'string') waitingScript = waitingScript.text();
			if (srcOrScript.indexOf(waitingScript) !== -1 || waitingScript.indexOf(srcOrScript) !== -1) {
				return true;
			}
		}
		return false;
	}

	/**
	 * if all scripts have been executed, fire a hook.
	 */

	function cmplz_run_after_all_scripts(category) {
		if (!all_scripts_hook_fired && cmplz_array_is_empty(waiting_inline_scripts) && cmplz_array_is_empty(waiting_scripts) ) {
			var event = new CustomEvent('cmplz_run_after_all_scripts', { detail: category });
			document.dispatchEvent(event);
			all_scripts_hook_fired = true;
		}
	}

	/**
	 * run inline script
	 * @param script
	 * @param category
	 */

	function cmplz_run_inline_script(script, category) {
		$('<script>')
			.attr('type', 'text/javascript')
			.text(script.text()).appendTo(script.parent());

        var all_scripts_executed = true;

		//get scripts that are waiting for this inline script
		var waitingScript = cmplz_get_waiting_script(waiting_scripts, script.text());
		if (waitingScript !== false) {
            all_scripts_executed = false;
			$.getScript(waitingScript)
				.done(function (s, Status) {
					//maybe all scripts are already done
					cmplz_run_after_all_scripts(category);
				})
				.fail(function (jqxhr, settings, exception) {
					console.warn("Something went wrong " + exception);
				});
		}

		var waiting_inline_script = cmplz_get_waiting_script(waiting_inline_scripts, script.text());
        if (waiting_inline_script) {
            all_scripts_executed = false;
            cmplz_run_inline_script(waiting_inline_script, category);
        }

        //maybe all scripts are already done
        if (all_scripts_executed) cmplz_run_after_all_scripts(category);

		script.remove();
	}

	/**
	 * Fire an event in Tag Manager
	 *
	 *
	 * */

	var cmplz_fired_events = [];
	function cmplz_run_tm_event(category) {
		if (cmplz_fired_events.indexOf(category) === -1) {
			cmplz_fired_events.push(category);
			window.dataLayer = window.dataLayer || [];
			window.dataLayer.push({
				'event': 'event_'+category
			});
			var event = new CustomEvent('cmplz_tag_manager_event', { detail: category });
			document.dispatchEvent(event);

		}
	}

	window.conditionally_show_banner = function() {
		//merge userdata with complianz data, in case a b testing is used with user specific cookie banner data
		//objects are merged so user_data will override data in complianz object
		complianz = cmplz_merge_object( complianz, cmplz_user_data );
		//check if we need to redirect to another legal document, for a specific region
		cmplzMaybeAutoRedirect();
		set_blocked_content_container();

		/**
		 * Integration with WordPress, tell what kind of consent type we're using, then fire an event
		 */

		window.wp_consent_type = complianz.consenttype;
		var event = new CustomEvent('wp_consent_type_defined');
		document.dispatchEvent( event );

	    var event = new CustomEvent('cmplz_before_cookiebanner' );
		document.dispatchEvent(event);

		if ( complianz.forceEnableStats == 1 ) {
			cmplz_set_consent('statistics', 'allow');
			$('.cmplz-description-statistics').addClass('cmplz-hidden');
			$('.cmplz-description-statistics-anonymous').removeClass('cmplz-hidden');
		}

		for (var key in categories) {
			var category = categories[key];
			if ( cmplz_has_consent(category) ) {
				cmplz_enable_category(category);
			}
		}

		var services = cmplz_get_services_on_page();
		for (var key in services) {
			var service = services[key];
			if ( cmplz_has_consent(service) ) {
				$('.cmplz-accept-service[data-service='+service+']').each(function(){
					$(this).prop('checked', true);
				});
				cmplz_enable_category('', service);
			}
		}

		var details = new Object();
		details.category = cmplz_highest_accepted_category();
		details.categories = cmplz_accepted_categories();
		details.region = complianz.region;
		event = new CustomEvent('cmplz_fire_categories', { detail: details });
		document.dispatchEvent(event);
		cmplz_sync_category_checkboxes();
		cmplz_integrations_init();
		cmplz_check_cookie_policy_id();
		cmplz_set_up_auto_dismiss();

		//if we're on the cookie policy page, we dynamically load the applicable revoke checkbox
		cmplz_load_manage_consent_container();

		event = new CustomEvent('cmplz_cookie_banner_data', { detail: complianz });
		document.dispatchEvent(event);

		//if no status was saved before, we do it now
		if ( cmplz_get_cookie('status_saved_once') !== 'true' ) {
			//for Non optin/optout visitors, and DNT users, we just track the no-warning option
			if ( complianz.consenttype !== 'optin' && complianz.consenttype !== 'optout' ) {
				cmplz_track_status('no_warning');
			} else if ( complianz.do_not_track ) {
				cmplz_track_status('do_not_track' );
			} else if (complianz.consenttype === 'optout') {
				//for opt out visitors, so consent by default
				cmplz_track_status();
			} else {
				//all others (eu): no choice yet.
				cmplz_track_status('no_choice');
			}
		}

		set_category_as_body_class();

		if (!complianz.do_not_track) {
			if (complianz.consenttype === 'optin') {
				if (complianz.forceEnableStats) {
					cmplz_enable_category('statistics');
				}
				console.log('opt-in');
				show_cookie_banner();
			} else if (complianz.consenttype === 'optout') {
				console.log('opt-out');
				show_cookie_banner();
			} else {
				console.log('other consent type, no cookie warning');
				//on other consent types, all scripts are enabled by default.
				cmplz_accept_all();
			}
		} else {
			cmplz_track_status( 'do_not_track' );
		}
	}

	/**
	 * Get list of services active on the page
	 * @returns {*[]}
	 */
	function cmplz_get_services_on_page(){
		var services=[];
		$('[data-service]').each(function(){
			var service = $(this).data('service');
			if (services.indexOf(service)==-1) {
				services.push(service);
			}
		});
		return services;
	}

	/**
	 * Run the actual cookie warning
	 *
	 * */


	window.show_cookie_banner = function () {
		var link = document.createElement("link");
		var pageLinks = complianz.page_links[complianz.region];
		//get correct banner, based on banner_id
		banner = $('.cmplz-cookiebanner.banner-'+complianz.user_banner_id+'.'+complianz.consenttype);
		manage_consent_button = $('#cmplz-manage-consent .cmplz-manage-consent.manage-consent-'+complianz.user_banner_id);
		link.href = complianz.css_file.replace('type', complianz.consenttype ).replace('banner_id', complianz.user_banner_id);
		link.type = "text/css";
		link.rel = "stylesheet";
		link.classList.add('cmplz-banner-css');
		document.getElementsByTagName("head")[0].appendChild(link);
		var disableCookiebanner = complianz.disable_cookiebanner;
		var temporarilyDismissBanner = false;
		//do not show banner when manage consent area on cookie policy is visible
		//when users use only the shortcode, the manage consent container is not active, but the dropdown cookie policy class is.
		//when the complianz shortcode is used, the dropdown cookie policy class is loaded late because it's loaded with javascript.
		if ( $('#cmplz-manage-consent-container').length || $('.cmplz-dropdown-cookiepolicy').length ) {
			temporarilyDismissBanner = true;
		}

		if ( !disableCookiebanner ) {
			banner.find('.cmplz-links a:not(.cmplz-external), .cmplz-buttons a:not(.cmplz-external)').each( function(){
				var docElement = $(this);
				docElement.addClass('cmplz-hidden');
				for (var pageType in pageLinks) {
					if ( docElement.hasClass(pageType) ){
						var curHref = docElement.attr('href');
						docElement.attr('href', curHref.replace('{url}',pageLinks[pageType]['url'] ));
						if ( docElement.html() === '{title}') {
							docElement.html(pageLinks[pageType]['title']);
						}
						docElement.removeClass('cmplz-hidden');
					}
				}
			});

			banner.find('.cmplz-manage-options.tcf').attr('href', pageLinks['cookie-statement']['url']);
			banner.addClass(complianz.region);
			cmplz_set_banner_status();
			//we don't use the setBannerStatus function here, as we don't want to save it in a cookie now.
			if (temporarilyDismissBanner) {
				banner.removeClass('cmplz-show');
				banner.addClass('cmplz-dismissed');
				manage_consent_button.removeClass('cmplz-dismissed');
				manage_consent_button.addClass('cmplz-show');
			}

			banner.removeClass('cmplz-hidden');
			manage_consent_button.removeClass('cmplz-hidden');
		}

		var event = new CustomEvent('cmplz_cookie_warning_loaded', {detail: complianz.region});
		document.dispatchEvent(event);
	}

	/**
	 * Get the status of the banner: dismissed | show
	 * @returns {string}
	 */
	window.cmplz_get_banner_status = function (){
		return cmplz_get_cookie('banner-status');
	}

	/**
	 * Set the banner status so it will be either shown or dismissed, and store it in a cookie.
	 * @param status (optional)
	 */

	window.cmplz_set_banner_status = function (status){
		var prevStatus = cmplz_get_cookie('banner-status');
		status = typeof status !== 'undefined' ? status : prevStatus;
		if ( status !== prevStatus ) {
			cmplz_set_cookie( 'banner-status', status );
		}
		if (status.length===0){
			status = 'show';
		}

		if (status==='show') {
			prevStatus = 'dismissed';
		} else {
			prevStatus = 'show';
		}

		if ( status.length>0 ) {
			banner.removeClass('cmplz-'+prevStatus);
			banner.addClass('cmplz-'+status );
			manage_consent_button.addClass('cmplz-'+prevStatus);
			manage_consent_button.removeClass('cmplz-'+status);
		}

		if (complianz.soft_cookiewall) {
			banner_container.removeClass('cmplz-'+prevStatus);
			banner_container.addClass('cmplz-'+status );
			banner_container.addClass('cmplz-soft-cookiewall');
		}
	}

	/**
	 * cmplz_banner_status: '' => visible, 'dismissed' => hidden.
	 */

	/**
	 * Check if there is consent for a category or service
	 * @param category
	 * @returns {boolean}
	 */
	window.cmplz_has_consent = function (category){
		if ( category === 'functional' ) return true;

		var has_consent;
		var value = cmplz_get_cookie(category);
		if (complianz.consenttype === 'optout' && value === '') {
			//if it's opt out and no cookie is set we should return true
			has_consent = true;
		} else {
			//all other situations, return only true if value is allow
			has_consent = (value === 'allow');
		}

		return has_consent;
	}

	/**
	 * Get cookie path
	 * @returns {*}
	 */
	function cmplz_get_cookie_path(){
		return typeof complianz.cookie_path !== 'undefined' && complianz.cookie_path !== '' ? complianz.cookie_path : '/';
	}

	/**
	 * retrieve domain to set the cookies on
	 * @returns {string}
	 */
	function cmplz_get_cookie_domain(){
		var domain = '';
		if ( complianz.set_cookies_on_root == 1 && complianz.cookie_domain.length>3){
			domain = complianz.cookie_domain;
		}
		if (domain.indexOf('localhost') !== -1 ) {
			domain = '';
		}
		return domain;
	}

	/**
	 * Set consent for a category
	 * @param category
	 * @param value
	 */
	window.cmplz_set_consent = function (category, value){
		if ( category === 'functional' && complianz.tm_categories == 1) {
			cmplz_run_tm_event(category);
			return;
		}

		cmplz_set_accepted_cookie_policy_id();
		var previous_value = cmplz_get_cookie(category);
		//do not trigger a change event if nothing has changed.
		if ( previous_value === value ) {
			return;
		}

		//keep checkboxes in banner and on cookie policy in sync
		var checked = value === 'allow';
		$('.cmplz-'+category).each(function(){
			$(this).prop('checked',checked );
		});

		cmplz_set_cookie(category, value);
		if ( value === 'allow' ) {
			cmplz_enable_category(category);
		}

		cmplz_wp_set_consent(category, value);
		if ( category === 'statistics' ) {
			cmplz_wp_set_consent('statistics-anonymous', 'allow');
		}

		if ( complianz.tm_categories == 1 ) {
			cmplz_run_tm_event( category);
		}

		var details = new Object();
		details.category = category;
		details.region = complianz.region;
		details.categories = cmplz_accepted_categories();
		var event = new CustomEvent('cmplz_status_change', { detail: details });
		document.dispatchEvent(event);

		cmplz_track_status();
		if ( category === 'marketing' && value === 'deny' ) {
			cmplz_integrations_revoke();
			location.reload();
		}
	}

	/**
	 * We use ajax to check the consenttype based on region, otherwise caching could prevent the user specific warning
	 *
	 * */

	var cmplz_user_data = [];
	//check if it's already stored
	if (typeof (Storage) !== "undefined" && sessionStorage.cmplz_user_data) {
		cmplz_user_data = JSON.parse(sessionStorage.cmplz_user_data);
	}

	//if not stored yet, load. As features in the user object can be changed on updates, we also check for the version
	if ( complianz.geoip == 1 && (cmplz_user_data.length == 0 || (cmplz_user_data.version !== complianz.version) || (cmplz_user_data.banner_version !== complianz.banner_version)) ) {
		var request = new XMLHttpRequest();

		request.open('GET', complianz.url.replace('/v1', '/v1/banner'), true);
		request.setRequestHeader('Content-type', 'application/json');
		request.send();
		request.onload = function() {
			cmplz_user_data = JSON.parse(request.response);
			sessionStorage.cmplz_user_data = JSON.stringify(cmplz_user_data);
			conditionally_show_banner();
		};
	} else {
		conditionally_show_banner();
	}

	/**
	 *  when ab testing, or using records of consent, we want to keep track of the unique user id
	 */

	if ( complianz.store_consent == 1 ) {
		var cmplz_id_cookie = cmplz_get_cookie('id');
		var cmplz_id_session = '';
		var cmplz_id = '';
		if (typeof (Storage) !== "undefined" && sessionStorage.cmplz_id) {
			cmplz_id_session = JSON.parse(sessionStorage.cmplz_id);
		}

		if ( cmplz_id_cookie.length == 0 && cmplz_id_session.length > 0 ) {
			cmplz_id = cmplz_id_session;
		}

		if ( cmplz_id_cookie.length > 0 && cmplz_id_session.length == 0 ) {
			cmplz_id = cmplz_id_cookie;
		}

		if ( typeof (Storage) !== "undefined" ) {
			sessionStorage.cmplz_id = JSON.stringify(cmplz_id);
		}
		cmplz_set_cookie('id', cmplz_id )
	}

	/**
	 * This creates an API which devs can use to trigger actions in complianz.
	 */
	document.addEventListener('cmplz_consent_action', function (e) {
		cmplz_set_consent( e.detail.category , 'allow' );
	});

	/**
	 * Accept all categories
	 */
	function cmplz_accept_all(){
		for (var key in categories) {
			cmplz_set_consent(categories[key], 'allow');
		}
	}

	/**
	 * Deny all categories, and reload if needed.
	 */
	function cmplz_deny_all(){
		for (var key in categories) {
			cmplz_set_consent(categories[key], 'deny');
		}

		var consentLevel = cmplz_highest_accepted_category();
		var reload = false;

		if (consentLevel !== 'functional' ) {
			reload = true;
		}
		if ( cmplz_clear_all_complianz_cookies('cmplz_service') ) {
			reload = true;
		}

		cmplz_integrations_revoke();
		cmplz_track_status();

		var event = new CustomEvent('cmplz_revoke', { detail: reload });
		document.dispatchEvent(event);

		//we need to let the iab extension handle the reload, otherwise the consent revoke might not be ready yet.
		if ( !complianz.tcf_active && reload ) {
			location.reload();
		}
	}

	/**
	 * For both opt-in and opt-out, clicking cmplz-accept should result in accepting all categories
	 */
	$(document).on('click', '.cmplz-accept', function(){
		cmplz_set_banner_status('dismissed');
		cmplz_accept_all();
	});

	/**
	 *  Accept marketing cookies by clicking any other link cookie acceptance from a custom link
	 */

	$(document).on('click', '.cmplz-accept-marketing', function (event) {
		event.preventDefault();
		var service = $(this).data('service');
		if ( service !== 'undefined' ){
			cmplz_set_consent(service, 'allow' );
			cmplz_enable_category('', service);
		} else {
			cmplz_set_consent('marketing', 'allow' );
			cmplz_enable_category('marketing');
		}
	});

	/**
	 * Accept a specific service
	 */
	$(document).on('change', '.cmplz-accept-service', function (event) {
		var service = $(this).data('service');
		if ( service !== 'undefined' ){
			if ( $(this).is(':checked') ){
				cmplz_set_consent(service, 'allow');
				cmplz_enable_category('', service);
			} else {
				cmplz_set_consent(service, 'deny');
				location.reload();
			}
		}
	});



	/**
	 * On the banner, clicking a category should fire the category only after the save button is clicked.
	 *
	 */
	$(document).on('click', '.cmplz-save-preferences', function(){
		for (var key in categories) {
			var category = categories[key];
			var categoryElement = $('.cmplz-'+category);
			if ( categoryElement.length ) {
				if ( categoryElement.is(":checked") ) {
					cmplz_set_consent(category, 'allow');
				} else {
					cmplz_set_consent(category, 'deny');
				}
			}
		}
		cmplz_set_banner_status('dismissed');
	});

	$(document).on('click', '.cmplz-close', function(){
		cmplz_set_banner_status('dismissed');
	});

	$(document).on('click', '.cmplz-view-preferences', function(){
		if ( $('.cmplz-categories').hasClass('cmplz-fade-in')) {
			$('.cmplz-categories').removeClass('cmplz-fade-in');
			$('.cmplz-view-preferences').show();
			$('.cmplz-save-preferences').hide();
		} else {
			$('.cmplz-categories').addClass('cmplz-fade-in');
			$('.cmplz-view-preferences').hide();
			$('.cmplz-save-preferences').show();
		}
	});
	/**
	 * On the cookie policy, clicking a category should fire the category immediately
	 *
	 */
	$(document).on('change', '.cmplz-manage-consent-container .cmplz-category', function(){
		console.log("changed category");
		for (var key in categories) {
			var category = categories[key];
			var categoryElement = $('.cmplz-manage-consent-container .cmplz-'+category);
			if ( categoryElement.length ) {
				if ( categoryElement.is(":checked") ) {
					cmplz_set_consent(category, 'allow');
				} else {
					cmplz_set_consent(category, 'deny');
				}
				cmplz_set_banner_status('dismissed');
			}
		}
	});

	$(document).on('click','.cmplz-deny', function(e){
		e.preventDefault();
		cmplz_deny_all();
		cmplz_set_banner_status('dismissed');
	});

	$(document).on('click', 'button.cmplz-manage-settings', function(e){
		e.preventDefault();
		var catsContainer = $('.cmplz-cookiebanner .cmplz-categories');
		var saveSettings = $('.cmplz-save-settings');
		var manageSettings = $('button.cmplz-manage-settings');
		if (catsContainer.is(":visible")){
			saveSettings.hide();
			manageSettings.show();
			catsContainer.fadeOut(800);
		} else {
			saveSettings.show();
			manageSettings.hide();
			catsContainer.fadeIn(800);
		}
	});

	$(document).on('click', 'button.cmplz-manage-consent', function(e){
		e.preventDefault();
		cmplz_set_banner_status('show');
	});

	/**
	 * Handle dismiss on scroll and dismiss on timeout
	 */
	function cmplz_set_up_auto_dismiss() {
		if ( complianz.consenttype === 'optout' ) {
			if ( complianz.dismiss_on_scroll==1 ) {
				var onWindowScroll = function(evt) {
					if (window.pageYOffset > Math.floor(400)) {
						cmplz_set_banner_status('dismissed');
						window.removeEventListener('scroll', onWindowScroll);
						this.onWindowScroll = null;
					}
				};
				window.addEventListener('scroll', onWindowScroll);
			}

			var delay = parseInt(complianz.dismiss_timeout);
			if ( delay > 0 ) {
				var cmplzDismissTimeout = window.setTimeout(function () {
					cmplz_set_banner_status('dismissed');
				}, Math.floor(delay));
			}
		}
	}

	//opt out
	//banner visible
	//optin

	/**
	 * Track the status of current consent
	 * @param status
	 */

	function cmplz_track_status( status ) {
		var cats = [];
		status = typeof status !== 'undefined' ? status : false;

		var event = new CustomEvent('cmplz_track_status', { detail: status });
		document.dispatchEvent(event);

		if ( !status ) {
			cats = cmplz_accepted_categories();
		} else {
			cats = [status];
		}


		set_category_as_body_class();
		if ( complianz.store_consent != 1 ) return;

		//keep track of the fact that the status was saved at least once
		cmplz_set_cookie('status_saved_once', 'true');
		var request = new XMLHttpRequest();
		request.open('POST', complianz.url.replace('/v1', '/v1/track'), true);
		var data = {
			'consented_categories': cats,
			'consenttype': window.wp_consent_type,//store the source consenttype, as our complianz.consenttype will not include optinstats.
		};

		request.setRequestHeader('Content-type', 'application/json');
		request.send(JSON.stringify(data));
	}

	/**
	 * Retrieve the highest level of consent that has been given
	 *
	 * */

	function cmplz_highest_accepted_category() {
		var consentedCategories = cmplz_accepted_categories();
		if (cmplz_in_array( 'marketing', consentedCategories )) {
			return 'marketing';
		}

		if (cmplz_in_array( 'statistics', consentedCategories )) {
			return 'statistics';
		}

		if (cmplz_in_array( 'preferences', consentedCategories )) {
			return 'preferences';
		}

		return 'functional';
	}

	/**
	 * Get accepted categories
	 *
	 * @returns {string}
	 */
	function cmplz_accepted_categories() {
		var consentedCategories = categories;
		var consentedTemp = [];

		//because array filter changes keys, we make a temp arr
		for (var key in consentedCategories) {
			var category = consentedCategories[key];
			if ( cmplz_has_consent(category)) {
				consentedTemp.push(category);
			}
		}

		consentedCategories = consentedCategories.filter(function(value, index, consentedCategories){
			return cmplz_in_array(value, consentedTemp);
		});
		return consentedCategories;
	}

	/**
	 * Enable the checkbox for each category which was enabled
	 *
	 * */

	function cmplz_sync_category_checkboxes() {
		for (var key in categories) {
			var category = categories[key];
			if ( cmplz_has_consent(category) || category === 'functional' ) {
				$('.cmplz-'+category).each(function(){
					$(this).prop('checked', true);
				});
			} else {
				$('.cmplz-'+category).each(function(){
					$(this).prop('checked', false);
				});
			}
		}
	}

	/**
	 * Merge two objects
	 *
	 * */

	function cmplz_merge_object(userdata, ajax_data) {
		var output = [];
		//first, we fill the important data.
		for (key in ajax_data) {
			if (ajax_data.hasOwnProperty(key)) output[key] = ajax_data[key];
		}

		//conditionally add static data
		for (var key in userdata) {
			//only add if not in ajax_data
			if (!ajax_data.hasOwnProperty(key) || typeof ajax_data[key] === 'undefined') {
				if (userdata.hasOwnProperty(key)) output[key] = userdata[key];
			}
		}

		return output;
	}

	/**
	 * If current cookie policy has changed, reset cookie consent
	 *
	 * */

	function cmplz_check_cookie_policy_id() {
		var user_policy_id = cmplz_get_cookie('policy_id');
		if (user_policy_id && (complianz.current_policy_id !== user_policy_id) ) {
			cmplz_clear_all_complianz_cookies('cmplz');
		}
	}

	/**
	 * Clear all our own cookies, to make sure path issues are resolved.
	 *
	 *
	 */
	function cmplz_clear_all_complianz_cookies(cookie_part){
		var foundCookie = false;

		if (typeof document === 'undefined') {
			return foundCookie;
		}
		var secure = ";secure";
		var date = new Date();
		date.setTime(date.getTime() - (24 * 60 * 60 * 1000));
		var expires = ";expires=" + date.toGMTString();
		if (window.location.protocol !== "https:") secure = '';
		(function () {
			var cookies = document.cookie.split("; ");
			for (var c = 0; c < cookies.length; c++) {
				var d = window.location.hostname.split(".");
				//if we have more than one result in the array, we can skip the last one, as it will be the .com/.org extension
				var skip_last = d.length > 1;
				while (d.length > 0) {
					var cookieName = cookies[c].split(";")[0].split("=")[0];
					var p = location.pathname;
					p = p.replace(/^\/|\/$/g, '').split('/');
					if ( cookieName.indexOf(cookie_part) !==-1 ) {
						foundCookie = true;
						var cookieBase = encodeURIComponent(cookieName) + '=;SameSite=Lax' + secure + expires +';domain=.' + d.join('.') + ';path=';
						var cookieBaseDomain = encodeURIComponent(cookieName) + '=;SameSite=Lax' + secure + expires +';domain=;path=';
						document.cookie = cookieBaseDomain + '/';
						document.cookie = cookieBase+ '/';
						while (p.length > 0) {
							var path = p.join('/');
							if ( path.length>0 ) {
								document.cookie = cookieBase + '/' + path;
								document.cookie = cookieBaseDomain + '/' + path;
								document.cookie = cookieBase + '/' + path + '/';
								document.cookie = cookieBaseDomain + '/' + path + '/';
							}
							p.pop();
						};
					}
					d.shift();
					//prevents setting cookies on .com/.org
					if (skip_last && d.length==1) d.shift();
				}
			}
		})();

		//to prevent a double reload, we preserve the cookie policy id.
		cmplz_set_accepted_cookie_policy_id();
		return foundCookie;
	}

	/**
	 *
	 * If a policy is accepted, save this in the user policy id
	 *
	 * */

	function cmplz_set_accepted_cookie_policy_id() {
		cmplz_set_cookie('policy_id', complianz.current_policy_id);
	}

	/**
	 * For supported integrations, initialize the not consented state
	 *
	 * */

	function cmplz_integrations_init() {
		var cookiesToSet = complianz.set_cookies;
		//check if we have scripts that need to be set to true on init.
		for (var key in cookiesToSet) {
			if (cookiesToSet.hasOwnProperty(key) && cookiesToSet[key][1] === '1') {
				cmplz_set_cookie(key, cookiesToSet[key][1], 0);
			}
		}
	}

	/**
	 * For supported integrations, revoke consent
	 *
	 * */
	function cmplz_integrations_revoke() {
		var cookiesToSet = complianz.set_cookies;
		for (var key in cookiesToSet) {
			if (cookiesToSet.hasOwnProperty(key)) {
				cmplz_set_cookie(key, cookiesToSet[key][1], 0);
			}
		}
	}

	/**
	 * For supported integrations, set consent
	 *
	 * */

	function cmplz_set_integrations_cookies() {
		var cookiesToSet = complianz.set_cookies;
		for (var key in cookiesToSet) {
			if (cookiesToSet.hasOwnProperty(key)) {
				cmplz_set_cookie(key, cookiesToSet[key][0]);
			}
		}
	}


	function cmplz_get_url_parameter(sPageURL, sParam) {
		if (typeof sPageURL === 'undefined') return false;

		var queryString = sPageURL.split('?');
		if (queryString.length == 1) return false;

		var sURLVariables = queryString[1].split('&'),
			sParameterName,
			i;
		for (i = 0; i < sURLVariables.length; i++) {
			sParameterName = sURLVariables[i].split('=');
			if (sParameterName[0] === sParam) {
				return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
			}
		}
		return false;
	}

	/**
	 * If the parameter cmplz_region_redirect =true is passed, find the user's region, and redirect.
	 */
	function cmplzMaybeAutoRedirect() {
		var redirect = cmplz_get_url_parameter(window.location.href, 'cmplz_region_redirect');
		var region = cmplz_get_url_parameter(window.location.href, 'cmplz-region');
		if (redirect && !region) {
			window.location.href = window.location.href + '&cmplz-region=' + complianz.region;
		}
	}

	/**
	 * wrapper to set consent for wp consent API. If consent API is not active, do nothing
	 * @param type
	 * @param value
	 */
	function cmplz_wp_set_consent(type, value) {
		//wp consent api integration
		if (typeof wp_set_consent == 'function') {
			wp_set_consent(type, value);
		}
	}

	/**
	 * Load revoke options
	 */

	function cmplz_load_manage_consent_container() {
		if ($('.cmplz-manage-consent-container').length) {
			var request = new XMLHttpRequest();
			request.open('GET', complianz.url.replace('/v1', '/v1/manage_consent_html'), true);
			request.setRequestHeader('Content-type', 'application/json');
			request.send();
			request.onload = function() {
				$('.cmplz-manage-consent-container').html(JSON.parse(request.response) );
				cmplz_sync_category_checkboxes();
			};
		}
	}

});
