/**
 * Vvveb
 *
 * Copyright (C) 2021  Ziadin Givan
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * https://github.com/givanz/Vvveb
 */

window.VvvebTheme = window.VvvebTheme || {ajax:{}};
window.VvvebApp = window.VvvebApp || {};
window.VvvebApp.path = document.currentScript.src.replace(/\/public.+$|assets-cache.+$|\/js.+$/, '');

VvvebTheme.Ajax = {
	call: function(url, parameters, element, selector, callback, requestType = "POST") {
		if (!url) {
			let action = element.closest("[data-v-vvveb-action]") ?? element;
			url = action.href ?? action.action ?? window.VvvebApp.path + '/index.php?module=' +  parameters["module"] + '&action=' + parameters["action"];
		} 
		
		if (!selector) {
			url += '&_component_ajax=' + parameters["component"] + '&_component_id=' + parameters["component_id"];
		}
	
		let loading = element?.querySelector('.loading');
		let btn = element?.querySelector('.button-text');
	
		if (loading && loading.classList.contains("d-none")) {
			loading.classList.remove('d-none');
			btn.classList.add('d-none');
		}
		
		if (element?.hasAttribute("button"))  {
			element.setAttribute("disabled", "true");
		}
	
		const controller = new AbortController();
		const signal = controller.signal;
		
		 fetch(url, {
			withCredentials: true,
			credentials: 'include',			
			method: requestType,   
			headers: {
			"X-Requested-With": "XMLHttpRequest",
		  },
		  signal: signal,
		  body: new URLSearchParams(parameters)})
		 .then(response => {
			if (!response.ok) { throw new Error(response) }
			if (response.redirected) { 
				controller.abort();
				window.location.href = response.url; 
			}
			
			return response.text()
		 })
		.then(data => {
			if (selector) {
				let response = new DOMParser().parseFromString(data, "text/html");
				if (!Array.isArray (selector) ) {
					selector = [selector];
				}
				
				for (const k in selector) {
					let elementSelector = selector[k];
					let currentElements = document.querySelectorAll(elementSelector);
					let newElements = response.querySelectorAll(elementSelector);
					
					if (currentElements && newElements) {
						currentElements.forEach( (e, i) => {
							let newElement = newElements[i] ?? document.createElement("null");
							e.replaceWith(newElement);
							newElement.querySelectorAll('script').forEach(oldScriptEl => {
								  const newScriptEl = document.createElement("script");
								  
								  Array.from(oldScriptEl.attributes).forEach( attr => {
									newScriptEl.setAttribute(attr.name, attr.value) 
								  });
								  
								  const scriptText = document.createTextNode(oldScriptEl.innerHTML);
								  newScriptEl.appendChild(scriptText);
								  
								  oldScriptEl.replaceChildren();
								  oldScriptEl.parentNode.replaceChild(newScriptEl, oldScriptEl);
								  oldScriptEl.remove();
								  
							});
						});
					} /*if (currentElements) {
						currentElements.forEach(e => e.remove());
					} else if (newElements) {
						//new elements don't  have corresponding elements on the page, reload hole page
						response = new DOMParser().parseFromString(data, "text/html")
						document.querySelector("body").replaceWith(response.querySelector("body"));
						break;
					}*/
				}
			}

			if (callback) callback(data);
			
			let loading = element?.querySelector('.loading');
			let btn = element?.querySelector('.button-text');
			
			if (loading && btn.classList.contains("d-none")) {
				loading.classList.add('d-none');
				btn.classList.remove('d-none');
			}
			
			if (element.hasAttribute("button")) {
				element.removeAttribute("disabled");
			}
		})
		.catch(error => {
			console.log(error);
			//displayToast("bg-danger", "Revision", "Error!");
		});				
	}
}

VvvebTheme.Cart = {
	
	module: 'cart/cart',
	component: 'cart',
	component_id: '0',
	
	ajax: function(action, parameters, element, selector, callback) {
		parameters['module']       = parameters['module'] ?? this.module;
		parameters['action']       = parameters['action']?? action;
		parameters['component']    = parameters['component'] ?? this.component;
		parameters['component_id'] = parameters['component_id'] ?? this.component_id;
		VvvebTheme.Ajax.call("", parameters, element,  selector, callback);
	},
	
	callback: function(data) {
		/*
			let miniCart = document.querySelectorAll("[data-v-component-cart]");
			if (miniCart) {
				miniCart[0].outerHTML = data;
			}*/
	},
	
	add: function(productId, options, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		if (options) {
			options['product_id'] = productId;
		} else {
			options = {'product_id':productId};
		}
		return this.ajax('add',options, element, selector, callback);
	},
	
	update: function(key, options, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		if (options) {
			options['key'] = key;
		} else {
			options = {'key':key};
		}
		return this.ajax('update',options, element, selector, callback);
	},
 
	remove: function(key, element, selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('remove', {'key':key}, element, selector, callback);
	},	
	
	coupon: function(options, element, selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('coupon', options, element, selector, callback);
	},	
	
	removeCoupon: function(options, element, selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('removeCoupon', options, element, selector, callback);
	}
}

VvvebTheme.Wishlist = {
	
	module: 'user/wishlist',
	component: 'wishlist',
	component_id: '0',
	
	ajax: function(action, parameters, element, selector, callback) {
		parameters['module'] = this.module;
		parameters['action'] = action;
		parameters['component'] = this.component;
		parameters['component_id'] = this.component_id;
		VvvebTheme.Ajax.call("", parameters, element,  selector, callback);
	},
	
	callback: function(data) {
	},
	
	add: function(productId, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('add',{'product_id':productId}, element, selector, callback);
	},
	
	update: function(productId, quantity, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('update',{'product_id':productId}, element, selector, callback);
	},
 
	remove: function(productId, element, selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('remove', {'product_id':productId}, element, selector, callback);
	}

}

VvvebTheme.Compare = {
	
	module: 'cart/compare',
	component: 'compare',
	component_id: '0',
	
	ajax: function(action, parameters, element, selector, callback) {
		parameters['module'] = this.module;
		parameters['action'] = action;
		parameters['component'] = this.component;
		parameters['component_id'] = this.component_id;
		VvvebTheme.Ajax.call("", parameters, element,  selector, callback);
	},
	
	callback: function(data) {
	},
	
	add: function(productId, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('add',{'product_id':productId}, element, selector, callback);
	},
	
	update: function(productId, quantity, element,  selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('update',{'product_id':productId}, element, selector, callback);
	},
 
	remove: function(productId, element, selector, callback = false) {
		if (!callback) callback = this.callback;
		return this.ajax('remove', {'product_id':productId}, element, selector, callback);
	}

}

VvvebTheme.Comments = {
	
	module: 'content/post',
	
	ajax: function(action, parameters, element,  selector, callback = false) {
		parameters['module'] = parameters['module'] ?? this.module;
		parameters['action'] = parameters['action'] ?? action;
		VvvebTheme.Ajax.call("", parameters, element, selector, callback);
	},
	
	add: function(parameters, element,  selector, callback = false) {
		return this.ajax('addComment',parameters, element, selector, callback);
	},
	
	update: function(productId, quantity, element, selector, callback = false) {
		return this.ajax('update',{'product_id':productId, 'quantity':quantity}, selector);
	},
	
	remove: function(productId) {
		return this.ajax('remove', {'product_id':productId}, selector);
	}
}

VvvebTheme.User = {
	
	module: 'user/login',
	component: 'user',
	component_id: '0',
	
	ajax: function(action, parameters, element, selector, callback = false) {
		parameters['module'] = parameters['module'] ?? this.module;
		parameters['action'] = parameters['action'] ?? action;
		parameters['component'] = parameters['component'] ?? this.component;
		parameters['component_id'] = parameters['component_id'] ?? this.component_id;
		
		VvvebTheme.Ajax.call("", parameters, element, selector, callback);
	},
	
	login: function(parameters, element, selector, callback = false) {
		return this.ajax('index' ,parameters, element, selector, callback);
	},
}

VvvebTheme.Search = {
	
	module: 'search',
	component: 'search',
	component_id: '0',
	
	ajax: function(action, parameters, element, selector, callback = false) {
		parameters['module'] = parameters['module'] ?? this.module;
		parameters['action'] = parameters['action'] ?? action;
		parameters['component'] = parameters['component'] ?? this.component;
		parameters['component_id'] = parameters['component_id'] ?? this.component_id;
		
		VvvebTheme.Ajax.call("/search", parameters, element, selector, callback);
	},
	
	query: function(parameters, element, selector, callback) {
		return this.ajax('index' ,parameters, element, selector, callback);
	},
}

VvvebTheme.Alert  = {
	
	show: function(message) {
		let alertTop = document.querySelector('.alert-top');
		alertTop.querySelector(".message").innerHTML = message;
		alertTop.classList.add("show");
		alertTop.style.display = "block";
		
		setTimeout(function () {
			alertTop.style.display = "none";
		}, 4000);
	}
}

document.querySelector('.alert-top .btn-close')?.addEventListener('click', function (e) {
    let alert = this.closest(".alert");
    alert.classList.remove('show')
    alert.style.display = "";
    e.preventDefault();
});

function objectSerialize(serializeArray) {
    let returnObject = {};
    for (let i = 0; i < serializeArray.length; i++){
        returnObject[serializeArray[i]['name']] = serializeArray[i]['value'];
    }
    return returnObject;
}


function elementProduct(element) {
	let product = element.closest("[data-v-product]");
	if (!product) {
		product = element.closest("[data-v-component-product]");
	}
	if (!product) {
		product = element.closest("[data-v-cart-product]");
	}	
	
	return product;
}

VvvebTheme.Gui = {
	
	init: function() {
		let events = [];
	
		document.querySelectorAll("[data-v-vvveb-action]").forEach(function (el) {

			let on = "click";
			if (el.dataset.vVvvebOn) on = el.dataset.vVvvebOn;
			
			if (events.indexOf(on) > -1) return;
			events.push(on);
			
			document.addEventListener(on, function (e) {
				let element = e.target.closest("[data-v-vvveb-action]");
				if (element) {
					let action = element.dataset.vVvvebAction;
					let elOn = element.dataset.vVvvebOn ?? "click";
					
					if (elOn == on && VvvebTheme.Gui.hasOwnProperty(action)) {
						VvvebTheme.Gui[action].call(e.target, e);
					}
				}
			});
		});
		
		/*
		document.querySelectorAll("[data-v-vvveb-action]").forEach(function (el) {

			let on = "click";
			if (el.dataset.vVvvebOn) on = el.dataset.vVvvebOn;
			let event = '[data-v-vvveb-action="' + el.dataset.vVvvebAction + '"]';

			if (events.indexOf(event + on) > -1) return;
			events.push(event + on);
			
			if (VvvebTheme.Gui.hasOwnProperty(el.dataset.vVvvebAction)) {
				document.addEventListener(on, function (e) {
					let element = e.target.closest("[data-v-vvveb-action]");
					if (element) {
						VvvebTheme.Gui[el.dataset.vVvvebAction].call(e.target, e);
					}
				});
				//document).addEventListener(on, VvvebTheme.Gui[this.dataset.vVvvebAction]);
			}
		});
		*/
	},
	
	addToCart: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let product = elementProduct(this);
		
		let img = product.querySelector("img[data-v-product-image], img[data-v-product-image-src], img[data-v-product-image], img[data-v-product-main-image]");
		let name = product.querySelector("[data-v-product-name]").textContent ?? "";
		let quantity = product.querySelector('[name="quantity"]')?.value ?? 1;
		let id = this.dataset.product_id ?? product.dataset.product_id;
		let options = {quantity};

		if (!id) {
			id = product.dataset.product_id;
			if (!id) {
				id = product.querySelector('input[name="product_id"]').value;
			}
		}
		
		let cart_add_text = 'was added to cart';
		let target = e.target.closest("button, input");

		if (target?.form) {
			options = Object.fromEntries(new URLSearchParams(new FormData(target.form)));
			if (!target.form.checkValidity()) {
				target.form.requestSubmit();
				return false;
			}
		}

		VvvebTheme.Cart.add(id, options, element, ['.mini-cart', '[data-v-notifications]'], function() {
			let src = img.getAttribute("src");
			VvvebTheme.Alert.show(`
			<div class="clearfix">
				<img  class="float-start me-2" height="80" src="${src}"> &ensp; 
				<div class="float-start"><a href="#">${name}<a><br> <span class="text-muted">${cart_add_text}<span></span></div>
			</div>
			<div class="row mt-2 g-2 " data-v-if="cart.total_items">
				  <div class="col-6">
					<a href="${window.VvvebApp.path}/cart" class="btn btn-light btn-sm border w-100" data-v-url="cart/cart/index">
					  <i class="la la-shopping-cart la-lg"></i>
					  <span>View cart</span>
					</a>
				  </div>
				  <div class="col-6">
					<a href="${window.VvvebApp.path}/checkout" class="btn btn-primary btn-sm w-100 px-2" data-v-url="checkout/checkout/index">
					  <span>Checkout</span>
					  <i class="la la-arrow-right la-lg"></i>
					</a>
				  </div>
			</div>`);
		});
		
		e.preventDefault();
		return false;
	},	
	
	removeFromCart: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		
		let product = this.closest("[data-v-product]");
		if (!product) {
			product = this.closest("[data-v-component-product]");
		}
		if (!product) {
			product = this.closest("[data-v-cart-product]");
		}
		let img = product.querySelector("[data-v-product-image],[data-v-product-image], [data-v-cart-product-image]")?.getAttribute("src") ?? "";
		let name = product.querySelector("[data-v-product-name]")?.textContent ?? "";
		let key = this.dataset.key;
		let selector = this.dataset.selector ?? '.cart-box';

		if (!key) {
			key = product.dataset.key;
			if (!key) {
				key = product.querySelector('input[name="key"]').value;
			}
		}
		
		let updatElements = ['.mini-cart', '[data-v-notifications]'];
		//if on cart page update also cart page elements
		for (selector of ['[data-v-cart]', '.cart-right-column']) {
			if (document.querySelector(selector)) {
				updatElements.push(selector);
			}
		}
		
		VvvebTheme.Cart.remove(key, element, updatElements, function() {
			product.remove();

			//if on cart page and cart empty refresh page
			let cartContainer = document.getElementById("cart-container");
			if (cartContainer && 
				cartContainer.querySelectorAll("[data-v-cart-product]").length == 0 ) {
				cartContainer.remove();
				location.reload();
			}		

			VvvebTheme.Alert.show('<img height=50 src="' + img + '"> &ensp; <strong>' +  name +'</strong> was removed from cart');
		});
		
		e.preventDefault();
		return false;
	},
	
	addToWishlist: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let product = elementProduct(this);
		let id = this.dataset.product_id ?? product.dataset.product_id;
		let img = product.querySelector("img[data-v-product-image], img[data-v-product-image], img[data-v-cart-product-image], img[data-v-product-main-image]")?.getAttribute("src") ?? "";

		if (!id) {
			id = product.dataset.product_id;
			if (!id) {
				id = product.querySelector('input[name="product_id"]').value;
			}
		}

		VvvebTheme.Wishlist.add(id, element, false, function(data) {
			VvvebTheme.Alert.show('<img height=50 src="' + img + '"> &ensp; <strong>' +  name +'</strong> was added to wishlist');
		});
		
		e.preventDefault();
		return false;
	},
	
	addToCompare: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let product = elementProduct(this);
		let id = this.dataset.product_id ?? product.dataset.product_id;
		let img = product.querySelector("img[data-v-product-image], img[data-v-product-image], img[data-v-cart-product-image], img[data-v-product-main-image]")?.getAttribute("src") ?? "";

		if (!id) {
			id = product.dataset.product_id;
			let input = product.querySelector('input[name="product_id"]');
			if (!id && input) {
				id = input.value;
			}
		}

		VvvebTheme.Compare.add(id, element, false, function(data) {
			VvvebTheme.Alert.show('<img height=50 src="' + img + '"> &ensp; <strong>' +  name +'</strong> was added to compare');
		});
		
		e.preventDefault();
		return false;
	},
	

	replyTo: function(e) {
		let commentId = this.dataset.comment_id;
		let commentAuthor = this.dataset.comment_author;
		let commentForm = document.getElementById("comment-form");
		//location.hash = "#comment-form";
		/*
		window.scrollTo({
		  top: commentForm.offsetTop + commentForm.clientHeight,
		  left: 0,
		  behavior: "smooth",
		});*/
		
		commentForm.querySelector("input[name=parent_id]").value = commentId;

		if (commentId > 0) {
			document.querySelector(".replyto").style.display = "";
			document.querySelector(".replyto [data-comment-author]").innerHTML = commentAuthor;
		} else {
			document.querySelector(".replyto").style.display = "none";
		}
		e.preventDefault();
		return false;
	},

	addComment: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let selector = this.dataset.selector ?? ".post-comments";
		let form = this;
		let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
		
		VvvebTheme.Comments.add(parameters, element, selector, function () {
			form.reset();
		});
		
		e.preventDefault();
	},	
	
	addReview: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let selector = this.dataset.selector ?? ".product-reviews";
		let form = this;
		let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
		parameters['module'] = 'product/product';
		parameters['action'] = 'addReview';
		
		VvvebTheme.Comments.add(parameters, element, selector, function () {
			form.reset();
		});
		
		e.preventDefault();
		
	},		
	
	addQuestion: function(e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let selector = this.dataset.selector ?? ".product-questions";
		let form = this;
		let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
		parameters['module'] = 'product/product';
		parameters['action'] = 'addQuestion';
		
		VvvebTheme.Comments.add(parameters, element, selector, function () {
			form.reset();
		});
		
		e.preventDefault();
	},	
	
	search: function (e) {
		clearTimeout(window.searchDebounce);
		let form = this;
		if (this.form) {
			form = this.form;
		}

		let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
		let element = this;
		let selector = this.dataset.selector;
		let loading = form.querySelector(".loading");
		if (loading) {
			loading.classList.remove('d-none');
		}
		
		document.querySelector(selector).replaceChildren();
		window.searchDebounce = setTimeout(function () {	
			VvvebTheme.Search.query(parameters, element, selector, function(data) { 
				if (loading) {
					loading.classList.add('d-none');
				}
			});
			e.preventDefault();
		
		}, 1000);
	},
	
	login: function (e) {
		let element = this.closest("[data-v-vvveb-action]") ?? this;
		let parameters = Object.fromEntries(new URLSearchParams(new FormData(this)));
		let componentUser;
		let url = this.dataset.vUrl ?? false;
		let selector = this.dataset.selector ?? '.user-box';
/*
		if (url) {
			VvvebTheme.User.module = url;
		}
*/
		componentUser = this.closest('[data-v-component-user]'); 
		//parameters['component_id'] = document.querySelectorAll('[data-v-component-user]').index(componentUser);

		VvvebTheme.User.login(parameters, element, selector/*, function(data) { 
			
			//document.querySelectorAll("[data-v-component-user]")[0].outerHTML = data;
			componentUser.html(data);
			//	alert("Login");
		}*/);
		e.preventDefault();
	},	
	
	//used to submit any form without refreshing page, used for contact forms
	submit: function (e) {
		let form = this;
		let parameters = Object.fromEntries(new URLSearchParams(new FormData(form)));
		let componentUser;
		let url = this.dataset.vUrl ?? false;
		let selector = this.dataset.selector;
		let loading = this.querySelector("button .loading, .btn .loading");
		
		if (loading) {
			loading.classList.remove("d-none");
			loading.parentNode.querySelector(".button-text")?.classList.add("d-none");
		}

		loadAjax(url, selector, () => {
			if (loading) {
				loading.classList.add("d-none");
				loading.parentNode.querySelector(".button-text")?.classList.remove("d-none");
				form.reset();
			}
		}, parameters, "post");

		e.preventDefault();
	}
}	

let delay = (function(){
  let timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

function isEditor () {
	return document.getElementById("vvvebjs-styles") || window.location.href.includes('r=');
}

let urlCache = {};

function preloadUrl(e) {
		delay(() => loadUrl(e, true), 200);
}
		
//ajax url
function loadAjax(url, selector, callback = null, params = {}, method = "get") {
	let options = {
		method,
		withCredentials: true,
		credentials: 'include'			
	};

	if (method == "post" && params) {
		options.body = new URLSearchParams(params);
	}
	
	if (!url) url = window.location.href;
	let progressPercent = 10;
	let progressTimer;
		
	if (VvvebTheme.ajax.progressStatus) {
		let progressTimer = () => {
		  if (progressPercent >= 95 || progressPercent == 0) {
			  clearTimeout(progressTimer);
		  } else {
			progressPercent += 5;
			setTimeout(progressTimer, 100);
		  }
		  VvvebTheme.ajax.progressStatus(progressPercent);
		}
		//show progress bar only if takes longer than 1 sec
		setTimeout(progressTimer, 1000);
	}
	
	fetch(url, options).
	then((response) => {
		//if (!response.ok) { throw new Error(response) }
		if (VvvebTheme.ajax.progressStatus && progressPercent > 10) {
			progressPercent = 100;
			VvvebTheme.ajax.progressStatus(progressPercent);
		}		
		return response.text();
	}).
	then(function (data) {
		if (selector) {
			let response = new DOMParser().parseFromString(data, "text/html");

			if (!Array.isArray (selector) ) {
				selector = [selector];
			}
			
			for (const k in selector) {
				let elementSelector = selector[k];
				let currentElements = document.querySelectorAll(elementSelector);
				let newElements = response.querySelectorAll(elementSelector);
				
				if (currentElements && newElements) {
					if (currentElements.length != newElements.length) {
						//new elements does not match corresponding elements on the page, reload hole page
						response = new DOMParser().parseFromString(data, "text/html")
						document.querySelector("body").replaceWith(response.querySelector("body"));
						break;
					}
				
					currentElements.forEach( (e, i) => {
						let newElement = newElements[i] ?? document.createElement("null");
						e.replaceWith(newElement);
						newElement.querySelectorAll('script').forEach(oldScriptEl => {
							  const newScriptEl = document.createElement("script");
							  
							  Array.from(oldScriptEl.attributes).forEach( attr => {
								newScriptEl.setAttribute(attr.name, attr.value) 
							  });
							  
							  const scriptText = document.createTextNode(oldScriptEl.innerHTML);
							  newScriptEl.appendChild(scriptText);

							  oldScriptEl.replaceChildren();
							  oldScriptEl.parentNode.replaceChild(newScriptEl, oldScriptEl);
							  oldScriptEl.remove();
							  
						});
					});
				} if (currentElements) {
					currentElements.forEach(e => e.remove());
				} else if (newElements) {
					//new elements don't  have corresponding elements on the page, reload hole page
					response = new DOMParser().parseFromString(data, "text/html")
					document.querySelector("body").replaceWith(response.querySelector("body"));
					break;
				}
			}
			
			if (callback) callback();
		}		

		if (VvvebTheme.ajax.progressStatus) {
			progressPercent = 0;
			VvvebTheme.ajax.progressStatus(0);
		}

		if (VvvebTheme.ajax.afterLoad) {
			VvvebTheme.ajax.afterLoad();
		}
		
		window.dispatchEvent(new CustomEvent("vvveb.loadUrl", {detail: {url, selector}}));
	}).catch(error => {
		console.log(error);
	});
}


VvvebTheme.ajax.selector        =  VvvebTheme.ajax.selector || "a[data-url], a[data-page-url], a[data-v-url], a[data-v-menu-item-url], a[data-v-post-url], a[data-v-product-url], a[data-v-cat-url], a[data-v-archive-url], a[data-v-admin-url], a[data-v-post-author-url], a[data-v-breadcrumb-item-url], a[data-v-categories-cat-url], a[data-v-cart-product-url]";
VvvebTheme.ajax.siteContainer   = VvvebTheme.ajax.siteContainer || ["#site-content", "body > section"];
VvvebTheme.ajax.scrollContainer = VvvebTheme.ajax.scrollContainer || "body";
VvvebTheme.ajax.skipUrl         = VvvebTheme.ajax.skipUrl || [];


if (!isEditor()) {
	document.addEventListener("click", function (e) {
		let element = e.target.closest(VvvebTheme.ajax.selector);
		if (element) {
			let url = element.getAttribute("href") ?? "";
			let regex = new RegExp("^.*//" + window.location.host);
			url = url.replace(regex, "");
			if (!url || (url.indexOf("//") != -1) || element.target //external url
				|| (VvvebTheme.ajax.skipUrl.length && (VvvebTheme.ajax.skipUrl.includes(url) || VvvebTheme.ajax.skipUrl.includes(window.location.pathname)))
			) return;
			
			let selector = element.dataset.selector || VvvebTheme.ajax.siteContainer;

			loadAjax(url, selector, () => { 
				//if (element.dataset.scroll) {
					let target          = document.querySelector(VvvebTheme.ajax.scrollContainer);
					let scrollTo        = element.dataset.scroll || (selector == VvvebTheme.ajax.siteContainer ? "start" : "center");
					target.scrollIntoView({behavior: "smooth", block: scrollTo, inline: scrollTo});
				//}
				window.history.pushState({url, selector}, null, url); 
			});
			
			e.preventDefault();
		}
	});
}

addEventListener("popstate", checkState);

function checkState(e) {
    if (e.state && e.state.url) {
        loadAjax(e.state.url, e.state.selector);
    }
}

window.history.pushState({url:window.location.pathname, selector:".content-body"}, null, window.location.href);


VvvebTheme.Gui.init();
