/**
 * Resources
 * https://github.com/InteractiveAdvertisingBureau/iabtcf-es
 * */
import {CmpApi} from '@iabtcf/cmpapi';
import {TCModel, TCString, GVL, Segment} from '@iabtcf/core';
import * as cmpstub from '@iabtcf/stub';
const cmplzCMP = 332;
const cmplzCMPVersion = 1;
const cmplzIsServiceSpecific = cmplz_tcf.isServiceSpecific == 1 ? true : false;
const cmplzExistingLanguages = ['bg', 'ca', 'cs', 'da', 'de', 'el', 'es', 'et', 'fi', 'fr', 'hr', 'hu', 'it', 'ja', 'lt', 'lv', 'mt', 'nl', 'no', 'pl', 'pt', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'zh',];
let cmplzLanguage = document.documentElement.lang.length ? document.documentElement.lang.substring(0,2) : 'en';
let cmplzLanguageJson;
var purposesUrl = cmplz_tcf.cmp_url+'cmp/vendorlist'+'/purposes-'+cmplzLanguage+'.json';

/**
 * initialize the __tcfapi function and post message
 * https://github.com/InteractiveAdvertisingBureau/iabtcf-es/tree/master/modules/stub
 */
cmpstub();

if (!cmplzExistingLanguages.includes(cmplzLanguage)) {
	cmplzLanguage = 'en';
	purposesUrl = cmplz_tcf.cmp_url+'cmp/vendorlist'+'/vendor-list.json';
}

jQuery(document).ready(function ($) {
	var bannerDataLoaded = $.Deferred();
	var tcModelLoaded = $.Deferred();
	var tcfLanguageLoaded = $.Deferred();
	var bannerLoaded = $.Deferred();
	var revoke = $.Deferred();

	fetch(purposesUrl, {
		method: "GET",
	}).then(response => response.json())
		.then(
			function(data){
				cmplzLanguageJson = data;
				tcfLanguageLoaded.resolve();
			}
	);

	document.addEventListener('wp_consent_type_defined', function (e) {
		bannerDataLoaded.resolve();
	});
	document.addEventListener('cmplzCookieWarningLoaded', function (e) {
		bannerLoaded.resolve();
	});
	document.addEventListener('cmplzRevoke', function (e) {
		const reload = e.detail;
		revoke.resolve(reload);
	});

	$.when(tcfLanguageLoaded).done(function() {
		GVL.baseUrl = cmplz_tcf.cmp_url+"cmp/vendorlist";
		let gvl = new GVL(cmplzLanguageJson);
		let sourceGvl = gvl.clone();
		let tcModel = new TCModel(gvl);
		tcModel.publisherCountryCode = cmplz_tcf.publisherCountryCode;
		tcModel.version = 2;
		tcModel.cmpId = cmplzCMP;
		tcModel.cmpVersion = cmplzCMPVersion;
		tcModel.isServiceSpecific = cmplzIsServiceSpecific;
		tcModel.UseNonStandardStacks = 0; //A CMP that services multiple publishers sets this value to 0
		const cmpApi = new CmpApi(cmplzCMP, cmplzCMPVersion, cmplzIsServiceSpecific);//Whether the signals encoded in this TC String were from service-specific storage (true) versus ‘global’ consensu.org shared storage (false).
		const storedTCString = cmplzGetTCString();
		/**
		 * After banner data is fully loaded
		 */

		tcModel.gvl.readyPromise.then(() => {
			const json = tcModel.gvl.getJson();
			let vendors = json.vendors;
			let vendorIds = cmplzFilterVendors(vendors);
			tcModel.gvl.narrowVendorsTo(vendorIds);

			//update model with given consents
			try {
				tcModel = TCString.decode(storedTCString, tcModel );
			} catch (err) {
				cmplzSetAllVendorLegitimateInterests();
				cmplzSetAllPurposeLegitimateInterests();
			}

			tcModelLoaded.resolve();
		});

		$.when(bannerDataLoaded, tcModelLoaded).done(function () {
			insertVendorsInPolicy(tcModel.gvl.vendors);

			if ( cmplzIsGDPR(complianz.region) ) {
				console.log("send TCF cmpApi update signal for model");
				console.log(tcModel);
				const encodedTCString = TCString.encode(tcModel);
				cmpApi.update(encodedTCString, cmplzUIVisible());

				var date = new Date();
				/**
				 * If the TC String was created over a year ago, we clear it.
				 */
				if (Date.parse(tcModel.created) < date.getTime() - 365 * 24 * 60 * 60 * 1000) {
					cmplzSetTCString(null );
				} else {
					cmplzSetTCString(encodedTCString);
				}
			} else {
				//in non gdpr regions
				cmpApi.update(null);
				cmplzSetTCString(null);
			}

			if ($('.cmplz-tcf-container').length) {
				$('.cc-revoke').fadeIn();
			}
		});

		$.when(bannerLoaded, tcModelLoaded, tcfLanguageLoaded).done(function () {
			configureBanner();
		});

		$.when(revoke).done(function (reload) {
			if (cmplzIsGDPR(complianz.region)) {
				revokeAllVendors(reload);
			}
		});

		/**
		 * When the accept all button is clicked, make sure all vendors are allowed
		 */

		document.addEventListener('cmplzAcceptAll', function (e) {
			//skip if not gdpr
			if (!cmplzIsGDPR(complianz.region)) {
				return;
			}
			acceptAllVendors();
		}, false);

		function acceptAllVendors() {
			cmplzSetAllVendorLegitimateInterests();

			tcModel.setAllPurposeLegitimateInterests();
			for (var key in cmplz_tcf.purposes) {
				tcModel.purposeConsents.set(cmplz_tcf.purposes[key]);
				cmplzSetTypeByVendor('purpose_legitimate_interest', cmplz_tcf.purposes[key]);
			}

			tcModel.setAllSpecialFeatureOptins()
			for (var key in cmplz_tcf.specialFeatures) {
				tcModel.specialFeatureOptins.set(cmplz_tcf.specialFeatures[key]);
				cmplzSetTypeByVendor('specialfeature', cmplz_tcf.specialFeatures[key]);
			}

			tcModel.setAllPurposeConsents();
			for (var key in cmplz_tcf.purposes) {
				tcModel.purposeConsents.set(cmplz_tcf.purposes[key]);
				cmplzSetTypeByVendor('purpose_consent', cmplz_tcf.purposes[key]);
			}

			tcModel.setAllVendorConsents();
			document.querySelectorAll('.cmplz-tcf-input').forEach(checkbox => {
				checkbox.checked = true;
			});
			const encodedTCString = TCString.encode(tcModel);
			cmpApi.update(encodedTCString, cmplzUIVisible());
			cmplzSetTCString(encodedTCString);
			cmplzTCFSetCookie('consent_status', 'allow', complianz.cookie_expiry);
		}

		function revokeAllVendors(reload) {
			//legint should be handled by right to object checkbox in vendor overview.
			// tcModel.unsetAllVendorLegitimateInterests();
			// tcModel.unsetAllPurposeLegitimateInterests();

			cmplzUnsetAllVendorLegitimateInterests();
			for (var key in cmplz_tcf.specialFeatures) {
				tcModel.specialFeatureOptins.set(cmplz_tcf.specialFeatures[key]);
				cmplzUnsetTypeByVendor('specialfeature', cmplz_tcf.specialFeatures[key]);
			}

			for (var key in cmplz_tcf.purposes) {
				tcModel.purposeConsents.set(cmplz_tcf.purposes[key]);
				cmplzUnsetTypeByVendor('purpose_consent', cmplz_tcf.purposes[key]);
			}

			tcModel.unsetAllVendorConsents();
			document.querySelectorAll('.cmplz-tcf-input').forEach(checkbox => {
				if (!checkbox.disabled) checkbox.checked = false;
			});

			const encodedTCString = TCString.encode(tcModel);
			cmpApi.update(encodedTCString, cmplzUIVisible());
			cmplzSetTCString(encodedTCString);
			cmplzTCFSetCookie('consent_status', 'dismiss', complianz.cookie_expiry);
			if (reload) {
				location.reload();
			}
		}

		/**
		 * Set all legitimate interests, except when a vendor does not have legints or special purposes.
		 */
		function cmplzSetAllVendorLegitimateInterests(){
			tcModel.setAllVendorLegitimateInterests();
			for (var key in tcModel.gvl.vendors ) {
				var vendor = tcModel.gvl.vendors[key];
				/**
				 * no legint, and no special purposes, set legint signal to 0.
				 */
				if ( vendor.legIntPurposes.length==0 && vendor.specialPurposes.length==0 ){
					tcModel.vendorLegitimateInterests.unset(vendor.id);
				}
			}
		}

		/**
		 * Set all purpose legint that are currently used
		 */
		function cmplzSetAllPurposeLegitimateInterests(){
			const purposes = cmplzIABfilterArray(cmplzLanguageJson.purposes, cmplz_tcf.purposes);
			for (var key in purposes) {
				const purpose = purposes[key];
				tcModel.purposeLegitimateInterests.set(purpose.id);
			}
		}

		/**
		 * UnSet all legitimate interests, except when a vendor does not have legints or special purposes.
		 */
		function cmplzUnsetAllVendorLegitimateInterests(){
			tcModel.unsetAllVendorLegitimateInterests();
			for (var key in tcModel.gvl.vendors ) {
				var vendor = tcModel.gvl.vendors[key];
				/**
				 * If a vendor only has special purposes, and no other purposes, there's no right to object.
				 */
				if (vendor.legIntPurposes.length==0 && vendor.purposes.length==0 && vendor.flexiblePurposes.length==0 && vendor.specialFeatures.length==0 && vendor.specialPurposes.length!=0){
					tcModel.vendorLegitimateInterests.set(vendor.id);
				}
			}
		}

		/**
		 * If a purpose has been selected/deselected, we need to re-check for al vendors if this has consenquences for legint
		 */
		function cmplzUpdateAllVendorLegitimateInterests(){
			for (var key in tcModel.gvl.vendors ) {
				var vendor = tcModel.gvl.vendors[key];

				/**
				 * no legint, and no special purposes, set legint signal to 0.
				 */
				if ( vendor.legIntPurposes.length==0 && vendor.specialPurposes.length==0 ){
					tcModel.vendorLegitimateInterests.unset(vendor.id);
				}

				if (vendor.legIntPurposes.length==0 && vendor.purposes.length==0 && vendor.flexiblePurposes.length==0 && vendor.specialFeatures.length==0 && vendor.specialPurposes.length!=0){
					tcModel.vendorLegitimateInterests.set(vendor.id);
				}
			}
		}

		/**
		 * We use this method to keep track of consents per vendor. This is not stored in the core tcString
		 *
		 * @param type
		 * @param typeId
		 */
		function cmplzSetTypeByVendor(type, typeId){
			if (type === 'purpose_consent') {
				tcModel.purposeConsents.set(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					if (sourceGvl.vendors[vendor.id].purposes.includes(typeId) && !vendor.purposes.includes(typeId)) {
						tcModel.gvl.vendors[vendor.id].purposes.push(typeId);
					}
				}
			}

			if (type === 'purpose_legitimate_interest') {
				tcModel.purposeLegitimateInterests.set(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					if (sourceGvl.vendors[vendor.id].purposes.includes(typeId) && !vendor.purposes.includes(typeId)) {
						tcModel.gvl.vendors[vendor.id].purposes.push(typeId);
					}
				}
			}

			if (type === 'specialfeature') {
				tcModel.specialFeatureOptins.set(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					if (sourceGvl.vendors[vendor.id].specialFeatures.includes(typeId) && !vendor.specialFeatures.includes(typeId)) {
						tcModel.gvl.vendors[vendor.id].specialFeatures.push(typeId);
					}
				}
			}

			if (type === 'feature') {
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					if (sourceGvl.vendors[vendor.id].features.includes(typeId) && !vendor.features.includes(typeId)) {
						tcModel.gvl.vendors[vendor.id].features.push(typeId);
					}
				}
			}
		}

		function cmplzUnsetTypeByVendor(type, typeId){
			if (type === 'purpose_consent') {
				tcModel.purposeConsents.unset(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					let index = vendor.purposes.indexOf(typeId);
					if (index > -1) {
						tcModel.gvl.vendors[vendor.id].purposes.splice(index, 1);
					}
				}
			}

			if (type === 'purpose_legitimate_interest') {
				tcModel.purposeLegitimateInterests.unset(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					let index = vendor.legIntPurposes.indexOf(typeId);
					if (index > -1) {
						tcModel.gvl.vendors[vendor.id].legIntPurposes.splice(index, 1);
					}
				}
			}

			if (type === 'specialfeature') {
				tcModel.specialFeatureOptins.unset(typeId);
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					const index = vendor.specialFeatures.indexOf(typeId);
					if (index > -1) {
						tcModel.gvl.vendors[vendor.id].specialFeatures.splice(index, 1);
					}
				}
			}

			if (type === 'feature') {
				for (var key in tcModel.gvl.vendors ) {
					var vendor = tcModel.gvl.vendors[key];
					const index = vendor.features.indexOf(typeId);
					if (index > -1) {
						tcModel.gvl.vendors[vendor.id].features.splice(index, 1);
					}
				}
			}
		}

		/**
		 * When revoke button is clicked, so banner shows again
		 *
		 */

		$(document).on('click', '.cc-revoke', function () {
			const storedTCString = cmplzGetTCString();
			cmpApi.update(storedTCString, true);  //just got the banner to show again, so we have to pass ui visible true
		});


		/**
		 * Create a checkbox, clickable
		 * @param type
		 * @param object
		 * @param container
		 * @param checked
		 * @param disabled
		 */
		function cmplzRenderCheckbox(type, object, container, checked, disabled) {
			let template = document.getElementById('cmplz-tcf-type-template').innerHTML;
			let description = object.descriptionLegal;
			const descArr = description.split('*');
			let header = descArr[0];
			descArr.splice(0, 1);
			description = header + '<ul><li>' + descArr.join('</li><li>') + '</li></ul>';
			template = template.replace(/{type_name}/g, object.name);
			template = template.replace(/{type_description}/g, description);
			template = template.replace(/{type_id}/g, object.id);
			template = template.replace(/{type}/g, type);

			const wrapper = document.createElement('div');
			wrapper.innerHTML = template;
			const checkbox = wrapper.firstChild;
			checkbox.querySelector('.cmplz-tcf-' + type + '-input').checked = checked;
			checkbox.querySelector('.cmplz-tcf-' + type + '-input').disabled = disabled;

			checkbox.querySelector('.cmplz-tcf-' + type + '-input').setAttribute('data-' + type + '_id', object.id);
			var fragment = document.createDocumentFragment();
			fragment.appendChild(checkbox);
			container.appendChild(checkbox);
		}

		/**
		 * Generate entire block of checkboxes with event listener
		 * @param type
		 * @param objects
		 * @param filterBy
		 */

		function generateTypeBlock(type, objects, filterBy) {
			let containerid = type;
			let srcPurposes;
			if (filterBy !== false) {
				containerid = filterBy + '-' + containerid;
				srcPurposes = cmplzGetPurposes(filterBy, false);
			}

			const container = document.getElementById('cmplz-tcf-' + containerid + 's-container');
			if (container === null) {
				return;
			}

			container.innerHTML = '';
			for (var key in objects) {
				if (objects.hasOwnProperty(key)) {
					const object = objects[key];
					let addItem = true;
					if (filterBy) {
						if (!srcPurposes.includes(object.id)) {
							addItem = false;
						}
					}

					if (addItem) {
						const object = objects[key];
						let checked = false;
						let disabled = false;
						if (type === 'purpose_consent') {
							checked = tcModel.purposeConsents.has(object.id);
						}
						if (type === 'purpose_legitimate_interest') {
							checked = tcModel.purposeLegitimateInterests.has(object.id);
						}
						if (type === 'specialfeature') {
							checked = tcModel.specialFeatureOptins.has(object.id);
						}
						if (type === 'feature') {
							checked = true;
						}
						if (type === 'specialpurpose') {
							checked = true;
							disabled = true;
						}

						cmplzRenderCheckbox(type, object, container, checked, disabled);
					}
				}
			}

			//add event listener
			$(document).on("click", '.cmplz-tcf-' + type + '-input', function () {
				const typeId = $(this).data(type + '_id');
				if ($(this).is(":checked")) {
					//set all of this id to checked
					$('[data-' + type + '_id=' +typeId+']').each(function(){
						$(this).prop('checked', true);
					});
					if (type==='purpose_consent'){
						tcModel.purposeConsents.set(typeId);
					}
					if (type==='purpose_legitimate_interest'){
						tcModel.purposeLegitimateInterests.set(typeId);
					}
					if ( type==='specialfeature') {
						tcModel.specialFeatureOptins.set(typeId);
					}
					cmplzSetTypeByVendor(type, typeId);
				} else {
					//set all of this id to unchecked
					$('[data-' + type + '_id=' +typeId+']').each(function(){
						$(this).prop('checked', false);
					});
					if (type==='purpose_consent'){
						tcModel.purposeConsents.unset(typeId);
					}
					if (type==='purpose_legitimate_interest'){
						tcModel.purposeLegitimateInterests.unset(typeId);
					}
					if ( type==='specialfeature') {
						tcModel.specialFeatureOptins.unset(typeId);
					}
					cmplzUnsetTypeByVendor(type, typeId);
				}
				cmplzUpdateAllVendorLegitimateInterests();

				//now we update the tcstring
				const encodedTCString = TCString.encode(tcModel);
				cmpApi.update(encodedTCString, true);
				cmplzSetTCString(encodedTCString);
			});


			$(document).on("click", '.cmplz-tcf-toggle', function (e) {
				e.preventDefault();
				let description = $(this).closest('label').find('.cmplz-tcf-type-description');

				if (!description.is(':visible')) {
					$(this).addClass('cmplz-tcf-rl').removeClass('cmplz-tcf-rm');
					description.show();
				} else {
					$(this).addClass('cmplz-tcf-rm').removeClass('cmplz-tcf-rl');
					description.hide();
				}
			});
		}

		function cmplzUIVisible() {
			let bannerVisible = true;
			const consentStatus = cmplzTCFGetCookie('consent_status');
			if (consentStatus !== '') {
				bannerVisible = false;
			}

			const policyVisible = document.getElementById('cmplz-tcf-vendor-container') !== null;
			return bannerVisible || policyVisible;
		}

		/**
		 * Create a list of checkable vendors in the cookie policy
		 * @param vendors
		 */

		function insertVendorsInPolicy(vendors) {
			//don't do this for non GDPR regions
			if (!cmplzIsGDPR(complianz.region)) return;
			const vendorContainer = document.getElementById('cmplz-tcf-vendor-container');
			if (vendorContainer === null) return;
			vendorContainer.innerHTML = '';
			const template = document.getElementById('cmplz-tcf-vendor-template').innerHTML;
			const purposes = cmplzIABfilterArray(cmplzLanguageJson.purposes, cmplz_tcf.purposes);
			const specialPurposes = cmplzIABfilterArray(cmplzLanguageJson.specialPurposes, cmplz_tcf.specialPurposes);
			const features = cmplzIABfilterArray(cmplzLanguageJson.features, cmplz_tcf.features);
			const specialFeatures = cmplzIABfilterArray(cmplzLanguageJson.specialFeatures, cmplz_tcf.specialFeatures);
			generateTypeBlock('purpose_consent', purposes, 'statistics');
			generateTypeBlock('purpose_consent', purposes, 'marketing');
			generateTypeBlock('purpose_legitimate_interest', purposes, 'statistics');
			generateTypeBlock('purpose_legitimate_interest', purposes, 'marketing');
			generateTypeBlock('feature', features, false);
			generateTypeBlock('specialpurpose', specialPurposes, false);
			generateTypeBlock('specialfeature', specialFeatures, false);

			if ( specialFeatures.length==0 ) {
				document.getElementById('cmplz-tcf-specialfeatures-wrapper').style.display = 'none';
			}

			for (var key in vendors) {
				if (vendors.hasOwnProperty(key)) {
					let customTemplate = template;
					const vendor = vendors[key];
					const vendorPurposes = vendor.purposes + vendor.legIntPurposes;
					let purposeString = '';
					for (var p_key in vendorPurposes) {
						if (vendorPurposes.hasOwnProperty(p_key)) {
							let purposeName = false;
							for (var src_p_key in purposes) {
								if (purposes.hasOwnProperty(src_p_key)) {
									if (purposes[src_p_key].id == vendorPurposes[p_key]) {
										purposeName = purposes[src_p_key].name;
									}
								}
							}
							if (purposeName) {
								const purposeLink = 'https://cookiedatabase.org/tcf/' + purposeName.replace(/ /g, '-').replace(/\//g, '-').toLowerCase();
								purposeString += '<div class="cmplz-tcf-purpose"><a href="' + purposeLink + '" target="_blank" rel="noopener noreferrer nofollow">' + purposeName + '</a></div>';
							}
						}
					}

					var retentionInDays = Math.round(vendor.cookieMaxAgeSeconds / (60 * 60 * 24));
					//if result is 0, get day in decimals.
					customTemplate = customTemplate.replace(/{cookie_retention_seconds}/g, vendor.cookieMaxAgeSeconds);
					customTemplate = customTemplate.replace(/{cookie_retention_days}/g, retentionInDays);
					customTemplate = customTemplate.replace(/{vendor_name}/g, vendor.name);
					customTemplate = customTemplate.replace(/{vendor_id}/g, vendor.id);
					customTemplate = customTemplate.replace(/{purposes}/g, purposeString);
					customTemplate = customTemplate.replace(/{privacy_policy}/g, vendor.policyUrl);

					const wrapper = document.createElement('div');
					wrapper.innerHTML = customTemplate;
					const checkbox = wrapper.firstChild;
					checkbox.querySelector('.cmplz-tcf-vendor-input').checked = tcModel.vendorConsents.has(vendor.id) || tcModel.vendorLegitimateInterests.has(vendor.id);
					checkbox.querySelector('.cmplz-tcf-vendor-input').setAttribute('data-vendor_id', vendor.id);

					//set consent
					checkbox.querySelector('.cmplz-tcf-consent-input').checked = tcModel.vendorConsents.has(vendor.id);
					checkbox.querySelector('.cmplz-tcf-consent-input').setAttribute('data-vendor_id', vendor.id);

					//show legint option if vendor has legintpurposes
					if ( vendor.legIntPurposes.length!=0 ){
						checkbox.querySelector('.cmplz_tcf_legitimate_interest_checkbox').style.display = 'block';
						checkbox.querySelector('.cmplz-tcf-legitimate-interest-input').setAttribute('data-vendor_id', vendor.id);
						checkbox.querySelector('.cmplz-tcf-legitimate-interest-input').checked = tcModel.vendorLegitimateInterests.has(vendor.id);
					}

					//handle non cookie access
					if (vendor.usesNonCookieAccess) {
						wrapper.querySelector('.non-cookie-storage-active').style.display = 'block';
					} else {
						wrapper.querySelector('.non-cookie-storage-inactive').style.display = 'block';
					}

					if (vendor.cookieRefresh) {
						wrapper.querySelector('.non-cookie-refresh-active').style.display = 'block';
					} else {
						wrapper.querySelector('.non-cookie-refresh-inactive').style.display = 'block';
					}

					if (vendor.cookieMaxAgeSeconds <= 0) {
						wrapper.querySelector('.session-storage').style.display = 'block';
					} else if (vendor.cookieMaxAgeSeconds <= 60 * 60 * 24) {
						wrapper.querySelector('.retention_seconds').style.display = 'block';
					} else {
						wrapper.querySelector('.retention_days').style.display = 'block';
					}

					var fragment = document.createDocumentFragment();
					fragment.appendChild(checkbox);
					vendorContainer.appendChild(checkbox);
				}
			}

			$(document).on("click", '.cmplz-tcf-legitimate-interest-input', function () {
				const vendorId = $(this).data('vendor_id');
				if ( $(this).is(":checked") ) {
					tcModel.vendorLegitimateInterests.set(vendorId);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-vendor-input').prop('checked', true);
				} else {
					tcModel.vendorLegitimateInterests.unset(vendorId);
				}
				//now we update the tcstring
				const encodedTCString = TCString.encode(tcModel);
				cmpApi.update(encodedTCString, true);
				cmplzSetTCString(encodedTCString);
				cmplzTCFSetCookie('consent_status', 'allow', complianz.cookie_expiry);
			});

			$(document).on("click", '.cmplz-tcf-consent-input', function () {
				const vendorId = $(this).data('vendor_id');
				if ($(this).is(":checked")) {
					tcModel.vendorConsents.set(vendorId);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-vendor-input').prop('checked', true);
				} else {
					tcModel.vendorConsents.unset(vendorId);
				}
				//now we update the tcstring
				const encodedTCString = TCString.encode(tcModel);
				cmpApi.update(encodedTCString, true);
				cmplzSetTCString(encodedTCString);
				cmplzTCFSetCookie('consent_status', 'allow', complianz.cookie_expiry);
			});

			$(document).on("click", '.cmplz-tcf-vendor-input', function () {
				const vendorId = $(this).data('vendor_id');
				if ($(this).is(":checked")) {
					tcModel.vendorConsents.set(vendorId);
					//positive leg int should not be set.
					tcModel.vendorLegitimateInterests.set(vendorId);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-legitimate-interest-input').prop('checked', true);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-consent-input').prop('checked', true);

				} else {
					tcModel.vendorConsents.unset(vendorId);
					tcModel.vendorLegitimateInterests.unset(vendorId);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-legitimate-interest-input').prop('checked', false);
					$(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-consent-input').prop('checked', false);
				}
				//now we update the tcstring
				const encodedTCString = TCString.encode(tcModel);
				cmpApi.update(encodedTCString, true);
				cmplzSetTCString(encodedTCString);
				cmplzTCFSetCookie('consent_status', 'allow', complianz.cookie_expiry);
			});

			$(document).on("click", '.cmplz-tcf-toggle-info', function (e) {
				e.preventDefault();
				$(this).toggle();

				container.find('.cmplz-tcf-info').toggle();
			});

			$(document).on("click", '.cmplz-tcf-toggle-vendor', function (e) {
				e.preventDefault();
				const container = $(this).closest('.cmplz-tcf-vendor-container').find('.cmplz-tcf-info');
				if (!container.is(':visible')) {
					$(this).addClass('cmplz-tcf-rl').removeClass('cmplz-tcf-rm');
					container.show();
				} else {
					$(this).addClass('cmplz-tcf-rm').removeClass('cmplz-tcf-rl');
					container.hide();
				}
			});

			$(document).on("click", "#cmplz-tcf-selectall", function () {
				for (var key in vendors) {
					if (vendors.hasOwnProperty(key)) {
						const vendor = vendors[key];
						tcModel.vendorConsents.set(vendor.id);
						document.querySelector('#cmplz-tcf-' + vendor.id).checked = true;
					}
				}
				const vendorCheckboxes = document.querySelectorAll('[data-vendor_id]');
				vendorCheckboxes.forEach(vendorCheckbox => {
					vendorCheckbox.checked = true;
				});
				acceptAllVendors();
			});

			$(document).on("click", "#cmplz-tcf-deselectall", function () {
				for (var key in vendors) {
					if (vendors.hasOwnProperty(key)) {
						const vendor = vendors[key];
						tcModel.vendorConsents.unset(vendor.id);
						document.querySelector('#cmplz-tcf-' + vendor.id).checked = false;
					}
				}
				revokeAllVendors(true);
			});

		}


	/**
	 * Filter the list of vendors
	 *
	 * @param vendors
	 * @returns {*}
	 */
	function cmplzFilterVendors(vendors) {
		let vendorIds = [];
		for (var key in vendors ) {
			if (vendors.hasOwnProperty(key)) {
				const vendor = vendors[key];
				vendorIds.push(vendor.id);
			}
		}
		let addVendorIds = cmplzFilterVendorsBy('purposes', vendors, cmplz_tcf.purposes);
		vendorIds = vendorIds.filter(value => addVendorIds.includes(value));

		addVendorIds = cmplzFilterVendorsBy('specialPurposes', vendors, cmplz_tcf.specialPurposes);
		vendorIds = vendorIds.filter(value => addVendorIds.includes(value));

		addVendorIds = cmplzFilterVendorsBy('features', vendors, cmplz_tcf.features);
		vendorIds = vendorIds.filter(value => addVendorIds.includes(value));

		addVendorIds = cmplzFilterVendorsBy('specialFeatures', vendors, cmplz_tcf.specialFeatures);
		vendorIds = vendorIds.filter(value => addVendorIds.includes(value));
		return vendorIds;
	}


	/**
	 * Get vendors who only have one of these purposes
	 * @param vendors
	 * @param category_purposes
	 * @returns {[]}
	 */
	function cmplzFilterVendorsBy(type, vendors, category_purposes) {
		let output = [];
		for (var key in vendors ) {
			if (vendors.hasOwnProperty(key)) {
				const vendor = vendors[key];
				//for each vendor purpose, check if it exists in the category purposes list. If not, don't add this vendor
				let allPurposesAreCategoryPurpose = true;
				const vendorProperties = vendor[type];
				for (var p_key in vendorProperties) {
					if (vendorProperties.hasOwnProperty(p_key)) {
						const purpose = vendorProperties[p_key];

						const inPurposeArray = category_purposes.includes(purpose);
						if (!inPurposeArray) {
							allPurposesAreCategoryPurpose = false;
						}
					}
				}
				const inOutPutArray = output.includes(vendor.id);
				if (!inOutPutArray && allPurposesAreCategoryPurpose) {
					output.push(vendor.id );
				}
			}
		}
		return output;
	}

	function cmplzGetTCString() {
		return window.localStorage.getItem('cmplz_tcf_consent' );
	}

	function cmplzSetTCString(value) {
		window.localStorage.setItem('cmplz_tcf_consent', value );
	}

	function cmplzGetPurposes(category, includeLowerCategories) {
		//these categories aren't used
		if ( category === 'functional' || category === 'preferences') {
			return [];
		}

		if (category === 'marketing' ) {
			if (includeLowerCategories) {
				return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
			} else {
				return [1, 2, 3, 4, 5, 6, 10];
			}
		} else if(category === 'statistics' ) {
			return [1, 7, 8, 9];
		}
	}

	/**
	 * Check if a region is a TCF region
	 * @param region
	 * @returns {boolean}
	 */
	function cmplzIsGDPR(region) {
		if (cmplzTCFinArray(region, complianz.tcf_regions) ){
			return true;
		}
		return false;
	}

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


	function configureBanner(){
		//don't do this for non GDPR regions
		if ( !cmplzIsGDPR(complianz.region) ) {
			return;
		}
		//the wrapper class makes sure TCF CSS is only applied in the correct regions
		$('#cc-window').addClass( 'cmplz-tcf-banner' );
		//$('#cc-window').addClass( 'cmplz-tcf-banner-hidden' );

		//wrap intro and categories in one div, which we can add a scrollbar to.
		$('.cc-message,.cmplz-tcf-category-expl').wrapAll('<div class="cmplz-tcf-main"></div>');

		//change class of the "view preferences" button
		//we need to check for this class to prevent erros on the preview
		if ( document.querySelector('.cc-show-settings') === null ) {
			return;
		}
		document.querySelector('.cc-show-settings').setAttribute('href', complianz.readmore_url+'#cmplz-manage-consent-container');
		document.querySelector('.cmplz-tcf-manage-vendors').setAttribute('href', complianz.readmore_url+'#cmplz-manage-consent-container');
		document.querySelector('.cc-show-settings').classList.remove("cc-btn-no-href");
		document.querySelector('.cc-show-settings').classList.remove("cc-show-settings");

		const srcMarketingPurposes = cmplzGetPurposes('marketing', false);
		const srcStatisticsPurposes = cmplzGetPurposes('statistics', false);

		/**
		 * Filter purposes based on passed purposes
		 */

		const marketingPurposes = cmplzIABfilterArray(cmplzIABfilterArray(cmplzLanguageJson.purposes, cmplz_tcf.purposes), srcMarketingPurposes);
		const statisticsPurposes = cmplzIABfilterArray(cmplzIABfilterArray(cmplzLanguageJson.purposes, cmplz_tcf.purposes), srcStatisticsPurposes);
		const features = cmplzIABfilterArray(cmplzLanguageJson.features, cmplz_tcf.features);
		const specialPurposes = cmplzIABfilterArray(cmplzLanguageJson.specialPurposes, cmplz_tcf.specialPurposes);
		const specialFeatures = cmplzIABfilterArray(cmplzLanguageJson.specialFeatures, cmplz_tcf.specialFeatures);

		const marketingPurposesContainer = document.querySelector('.cmplz-tcf-expl-desc.marketing-purposes');
		const statisticsPurposesContainer = document.querySelector('.cmplz-tcf-expl-desc.statistics-purposes');
		const featuresContainer = document.querySelector('.cmplz-tcf-expl-desc.features');
		const specialFeaturesContainer = document.querySelector('.cmplz-tcf-expl-desc.specialFeatures');
		const specialPurposesContainer = document.querySelector('.cmplz-tcf-expl-desc.specialPurposes');

		if (features.length === 0 ) document.querySelector('#cc-window .features').closest('.cmplz-dropdown').style.display = 'none';
		if (specialPurposes.length === 0 ) document.querySelector('#cc-window .specialPurposes').closest('.cmplz-dropdown').style.display = 'none';
		if (specialFeatures.length === 0 ) document.querySelector('#cc-window .specialFeatures').closest('.cmplz-dropdown').style.display = 'none';
		if (statisticsPurposes.length === 0 ) document.querySelector('#cc-window .statistics-purposes').closest('.cmplz-dropdown').style.display = 'none';

		statisticsPurposesContainer.innerHTML = cmplzConcatenateString( statisticsPurposes );
		marketingPurposesContainer.innerHTML = cmplzConcatenateString( marketingPurposes );
		featuresContainer.innerHTML = cmplzConcatenateString( features );
		specialFeaturesContainer.innerHTML = cmplzConcatenateString( specialFeatures );
		specialPurposesContainer.innerHTML = cmplzConcatenateString( specialPurposes );

		//on pageload, show vendorlist area
		$('#cmplz-tcf-wrapper').show();
		$('#cmplz-tcf-wrapper-nojavascript').hide();
		$('.cmplz-tcf-banner').removeClass('cmplz-tcf-banner-hidden');
	}

	function cmplzIABfilterArray(arrayToFilter, arrayToFilterBy){
		let output = [];
		for (var key in arrayToFilter ) {
			if (arrayToFilterBy.includes(arrayToFilter[key].id)) {
				output.push(arrayToFilter[key]);
			}
		}
		return output;
	}

	function cmplzConcatenateString(array) {
		let string = '';
		const max = array.length-1;
		for (var key in array ) {
			if (array.hasOwnProperty(key)) {
				string += array[key].name;
				if ( key < max ) {
					string += ', ';
				} else {
					string += '.';
				}
			}
		}
		return string;
	}

	function cmplzTCFSetCookie(name, value, days) {
		var cmplzPrefix = 'cmplz_';
		if ( complianz.is_multisite_root ) {
			cmplzPrefix = 'cmplz_rt_'
		}
		name = cmplzPrefix+name;
		var secure = ";secure";
		var date = new Date();
		date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
		var expires = ";expires=" + date.toGMTString();

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

		var domain = cmplzTCFGetCookieDomain();
		if (domain.length > 0) {
			domain = ";domain=" + domain;
		}
		document.cookie = name + "=" + value + ";SameSite=Lax" + secure + expires + domain + ";path="+cmplzTCFGetCookiePath();
	}

	function cmplzTCFGetCookie(cname) {
		var cmplzPrefix = 'cmplz_';
		if ( complianz.is_multisite_root ) {
			cmplzPrefix = 'cmplz_rt_'
		}
		var name = cmplzPrefix+cname + "=";
		var cArr = window.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 "";
	}

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

		function cmplzTCFGetCookieDomain(){
			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;
		}
	});
});
