class CBHeader {
	constructor(header, arrow_down, arrow_up) {
		this.header = header;
		this.logo = this.header.querySelector('a'); //Header part 1
		this.burgerBtn = this.header.querySelector('button'); //Header part 2
		this.mainMenu = this.header.querySelector('ul'); //Header part 3
		this.loginMenu = this.header.querySelector('nav'); //Header part 4
		this.arrow_down = arrow_down;
		this.arrow_up = arrow_up;
	}

	init() {
		window.addEventListener('resize', (e) => {
			this.checkResponsive();
		});
		this.checkResponsive();
		this.toggleMobileMenu();
	}

	checkResponsive() {
		const width = window.innerWidth;
		if (
			width <= 1100 && this.header.classList.contains('mobile') ||
			width > 1100 && !this.header.classList.contains('mobile')
		) {
			return;
		}

		//Remove the header content
		this.header.innerHTML = '';

		//Add the mobile menu and login menu to the mobile wrapper
		if (width <= 1100) {
			this.header.classList.add('mobile');
			let mobileWrapper = document.createElement('section');
			let mobileMenu = this.mainMenu.cloneNode(true);

			//Add arrow icons to the menu items that have children
			mobileMenu.querySelectorAll('li').forEach(el => {
				if (el.querySelector('ul') !== null) {
					el.querySelector('a').insertAdjacentHTML('afterend', `<button onclick="this.parentNode.classList.toggle('active');">${this.arrow_down}</button>`);
				}
			});

			//Add the mobile menu and login menu to the mobile wrapper
			mobileWrapper.append(mobileMenu, this.loginMenu);
			this.header.append(this.logo, this.burgerBtn, mobileWrapper);
			this.toggleMobileSubMenu();
		}

		//Add the desktop menu and login menu to the header
		if (width > 1100) {
			this.header.classList.remove('mobile');
			this.header.append(this.logo, this.mainMenu, this.loginMenu);
		}
	}

	toggleMobileMenu() {
		this.header.querySelector('button').addEventListener('click', (e) => {
			e.preventDefault();
			this.header.classList.toggle('active');

			//Close all submenus when the mobile menu is closed
			if (!this.header.classList.contains('active')) {
				this.header.querySelector('nav').querySelector('button').classList.remove('active');
				this.header.querySelectorAll('section > ul > li').forEach(el => {
					el.classList.remove('active');
				});
			}
		});
	}

	toggleMobileSubMenu() {
		// this.header.querySelectorAll('section > ul > li > a').forEach(el => {
		// 	const parent = el.parentElement;
		// 	if (parent.querySelector('ul'))
		// 		el.addEventListener('click', (e) => {
		// 			if (!parent.classList.contains('active')) {
		// 				e.preventDefault();
		// 				parent.classList.toggle('active');
		// 			}
		// 		});
		// });
	}
}

CBFooter = function () {
	//Handle scroll to anchor links with offset.
	function scrollToAnchor(elName) {
		const targetElement = document.querySelector(`a[name=${elName}]`);
		if (targetElement) {
			const headerOffset = 80;
			const elementPosition = targetElement.getBoundingClientRect().top + window.scrollY;
			const offsetPosition = elementPosition - headerOffset;
			window.scrollTo({
				top: offsetPosition,
				behavior: "smooth"
			});
		}
	}

	//Add event sto links with hash
	document.querySelectorAll('a[href^="#"]').forEach(anchor => {
		anchor.addEventListener("click", function (e) {
			e.preventDefault();
			const elName = this.getAttribute("href").substring(1);
			scrollToAnchor(elName);
		});
	});

	//Scroll to anchor if hash is present in URL
	if (window.location.hash) {
		setTimeout(() => {
			const elName = window.location.hash.substring(1);
			scrollToAnchor(elName);
		}, 100); // Small delay to ensure the page is loaded before scrolling
	}
}

function CBError(errors){
	var _errno=null;
	var _error=null;
	function errno(){return _errno;}
	function error(){return _error;}
	function reset(){_errno=null;error=null;}
	function set(errno,replaceObj,ret){
		_errno=errno;
		_error=errors[errno];
		for(let i in replaceObj){
			_error=_error.replace('{'+i+'}',replaceObj[i]);
		}
		if(typeof(ret)=='undefined'){ret=false;}
		return ret;
	}
	return {
		errno	:errno,
		error	:error,
		reset	:reset,
		set		:set
	}
}


function CBCurrenciesTable(
	currencyFilterEl,dateFilterEl,dataTableEl,dateEl,unavailableEl,unavailableDateEl,errorEl,
	optionAllTpl,optionTpl,trTpl,
	columnsOrder
){
	this.el={
		currencyFilter	:currencyFilterEl,
		dateFilter		:dateFilterEl,
		dataTable		:dataTableEl,
		date			:dateEl,
		unavailable		:unavailableEl,
		unavailableDate	:unavailableDateEl,
		error			:errorEl
	}
	this.tpl={
		option		:optionTpl,
		optionAll	:optionAllTpl,
		tr			:trTpl
	}
	this.order=columnsOrder;

	this.currencyFilterChange=function(){
		var IBAN=this.el.currencyFilter.value;
		var rows=this.el.dataTable.querySelectorAll('tr');
		var cell=null;
		for(let i=0;i<rows.length;i++){
			cell=rows[i].querySelectorAll('td')[1].textContent;
			if(cell===IBAN||IBAN===''){
				rows[i].style.display='';
				continue;
			}
			rows[i].style.display='none';
		}
	};

	this.cleanPage=function(){
		this.el.dataTable	.innerHTML				='';
		this.el.date		.innerHTML				='';
		this.el.error		.innerHTML				='';
		this.el.unavailable	.style		.display	='';
	}

	this.populateCurrencyFilter=function(fx){
		var html=[];
		html.push(this.tpl.optionAll);
        for(const [code,rates] of Object.entries(fx)){
			html.push(this.tpl.option.replace(/{code}/g,code).replace(/{name}/g,rates.name));
		}
		this.el.currencyFilter.innerHTML=html.join('');
	}

	this.populateCurrency=function(fx){
		var html=[];
        for(const [code,rates] of Object.entries(fx)){
			html.push(this.tpl.tr
				.replace(/\{code\}/g	,code)
				.replace(/\{name\}/g	,rates.name)
				.replace(/\{0\}/g		,rates[this.order[0]])
				.replace(/\{1\}/g		,rates[this.order[1]])
				.replace(/\{2\}/g		,rates[this.order[2]])
				.replace(/\{3\}/g		,rates[this.order[3]])
				.replace(/\{4\}/g		,rates[this.order[4]])
			);
		}
		this.el.dataTable.innerHTML=html.join('');
	}

	this.displayError=function(msg){
		this.el.error		.textContent=msg;
	}

	this.dateFilterChangeXHR=function(prog){
		if(prog.currentTarget.status==200){
			var resp=JSON.parse(prog.currentTarget.responseText);
			this.el.date.textContent=resp.date_formatted;
			this.populateCurrencyFilter(resp.fx);
			this.populateCurrency(resp.fx);
			return;
		}
		if(prog.currentTarget.status==404){
			var resp=JSON.parse(prog.currentTarget.responseText);
			this.el.unavailable.style.display	='block';
			this.el.unavailableDate.textContent	=resp.date_formatted;
			return;
		}
		if(prog.currentTarget.status==400){
			this.displayError('Invalid date');
			return;
		}
		this.displayError('Unknown error');
	}

	this.dateFilterChange=function(){
		this.cleanPage();
		var date=this.el.dateFilter.value;
		var xhr=new XMLHttpRequest();
		xhr.open('GET', `${window.location.pathname}?d=${date}`);
		xhr.onload=this.dateFilterChangeXHR.bind(this);
		xhr.send();
	};


	this.init=function(){
		currencyFilterEl	.addEventListener('change',this.currencyFilterChange	.bind(this));
		dateFilterEl		.addEventListener('change',this.dateFilterChange		.bind(this));
	};
	this.init();
}


function CBSimpleExchangeRateCalculator(
	transactionType,
	currency,
	amount,
	amountIn,
	rateDisplay,
	conversionDisplay1,
	conversionDisplay2,
	conversionDisplay3,
	exchangeTpl,
	convertTpl,
	errorTpl,
	fxRates,
	home,
	reasons
){

	function update() {
		V.amountIn(transactionType.value,currency.value,home.code);
		var a=D.run(transactionType.value,currency.value,amount.value);
		if(a===false){
			if(D.errno()==1){	V.error('Please select a Conversion Type'			);return;}
			if(D.errno()==2){	V.error("Once you've entered an amount, your results will appear here.");return;}
			if(D.errno()==3){	V.error('Please provide a numeric Amount'			);return;}
		}
		for(let i=0;i<a.results.length;i++){
			a.results[i].reason=reasons[a.results[i].reason];
		}
		V.success(
			a.from.amount,a.from.decimals,a.from.code,a.results
		);
	}

	function init(){
		transactionType	.addEventListener('change'	,update);
		currency		.addEventListener('change'	,update);
		amount			.addEventListener('input'	,update);
		update();
	}

	var D=CBSimpleExchangeRateCalculator_Data(fxRates,home);
	var V=CBSimpleExchangeRateCalculator_View(
		amountIn,rateDisplay,[conversionDisplay1,conversionDisplay2,conversionDisplay3],
		exchangeTpl.innerHTML,convertTpl.innerHTML,errorTpl.innerHTML
	);
	init();
}


function CBSimpleExchangeRateCalculator_Data(fxRates,home){
	for(let i in fxRates){
		fxRates[i].buy_air		=parseFloat(fxRates[i].buy_air		);
		fxRates[i].buy_notes	=parseFloat(fxRates[i].buy_notes	);
		fxRates[i].buy_tt		=parseFloat(fxRates[i].buy_tt		);
		fxRates[i].sell_notes	=parseFloat(fxRates[i].sell_notes	);
		fxRates[i].sell_tt		=parseFloat(fxRates[i].sell_tt		);
		fxRates[i].decimals		=parseFloat(fxRates[i].decimals		);
	}
	_errno=0;
	function errno(){
		return _errno;
	}
	function run(transactionType,currency,amountStr){
		_errno=0;
		if(!amountStr							){		_errno=2;   return false;}
		if(isNaN(amount=parseFloat(amountStr	))){	_errno=3;   return false;}
		if(transactionType=='to'){
			return {
				from:{
					amount		:amount,
					decimals	:2,
					code		:currency
				},
				results:[
					{
						reason		:'buy_notes',
						amount		:fxRates[currency].buy_notes	==0?0:amount	/fxRates[currency].buy_notes	,
						decimals	:fxRates[currency].decimals,
						code		:home.code
					},
					{
						reason		:'buy_tt',
						amount		:fxRates[currency].buy_tt		==0?0:amount	/fxRates[currency].buy_tt		,
						decimals	:fxRates[currency].decimals,
						code		:home.code
					},
					{
						reason		:'buy_air',
						amount		:fxRates[currency].buy_air		==0?0:amount	/fxRates[currency].buy_air		,
						decimals	:fxRates[currency].decimals,
						code		:home.code
					},
				]
			}
		}
		if(transactionType=='from'){
			return {
				from:{
					amount		:amount,
					decimals	:2,
					code		:home.code
				},
				results:[
					{
						reason		:'sell_notes',
						amount		:fxRates[currency].sell_notes	==0?0:amount*	fxRates[currency].sell_notes	,
						decimals	:fxRates[currency].decimals,
						code		:currency
					},
					{
						reason		:'sell_tt',
						amount		:fxRates[currency].sell_tt		==0?0:amount	*fxRates[currency].sell_tt		,
						decimals	:fxRates[currency].decimals,
						code		:currency
					},
				]
			};
		}
		_errno=1;
		return false;
	}
	return {
		run		:run,
		errno	:errno
	};
}


function CBSimpleExchangeRateCalculator_View(
	amountInEl,rateDisplay,conversions,
	exchangeTpl,convertTpl,errorTpl
){
	function exchange(	amount,decimals,code		){
		return exchangeTpl.replace('{amount_code}',_format(amount,decimals,code));
	}
	function convert(	amount,decimals,code,reason	){
		if(amount==0){
			return convertTpl.replace('{reason}',reason).replace('{amount_code}','Not available'				);
		}
			return convertTpl.replace('{reason}',reason).replace('{amount_code}',_format(amount,decimals,code)	);
	}

	function _here(){Intl.DateTimeFormat().resolvedOptions().locale;}

	function _format(amount,decimals,code){
		amount=amount.toLocaleString(_here(),{style:'decimal',minimumFractionDigits:decimals,maximumFractionDigits:decimals});
		return `${amount} ${code}`;
	}
	function success(fromAmount,fromDecimals,fromCode,results){
		rateDisplay			.innerHTML		=exchange(fromAmount,fromDecimals,fromCode);
		rateDisplay			.style.display	='block';

		for(let i=0;i<conversions.length;i++){
			conversions[i]	.innerHTML		='';
			conversions[i]	.style.display	='none';
		}
		for(let i=0;i<results.length;i++){
			conversions[i]	.innerHTML		=convert(results[i].amount,results[i].decimals,results[i].code,results[i].reason);
			conversions[i]	.style.display	='block';
		}
	}

	function error(msg){
		rateDisplay			.innerHTML		=errorTpl.replace('{error}',msg);
		rateDisplay			.style.display	='block';
		for(let i=0;i<conversions.length;i++){
			conversions[i]	.style.display	='none';
		}
	}

	function amountIn(transactionType,foreignCode,homeCode){
		if(transactionType=='from'){
			amountInEl.textContent=homeCode;
			return;
		}
		if(transactionType=='to'){
			amountInEl.textContent=foreignCode;
			return;
		}
	}

	return {
		'success'	:success,
		'error'		:error,
		'amountIn'	:amountIn
	}
}
