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
	}
}


var CBMultipinMap = function (options) {
	var self = this;
	this.location = options.selectLocation;
	this.autoComplete_list = options.selectAutoComplete;
	this.keywords = options.textSearch;
	this.resultNav = options.navTypes;
	this.btnNearBy = options.btnNearBy;
	this.resultWrapper = options.resultWrapper;
	this.detailsWrapper = options.detailsWrapper;
	this.data = options.data;
	this.icons = options.icons;
	this.map = null;
	this.markers = [];
	this.clusterLayer = null;
	this.svg = options.svg;
	this.iconATM = options.iconATM;
	this.iconBranch = options.iconBranch;
	this.currentListing = [];
	this.default_country = options.default_country;

	console.log(this.default_country);
	this.init = function () {
		self.loadCountriesAndTypes();
		self.renderMap();
	};

	this.setupMapFunctions = function () {
		self.setupClusterClicked(self.map);
		self.setupUnclusterClicked(self.map);
		self.setupFilterByType();
		self.setupFilterByCountry();
		self.setupBtnNearBy();
		self.setupSearchByKeywords();
		self.filterLocationsByType("all");
	};

	this.renderMap = function () {
		mapboxgl.accessToken = 'pk.eyJ1IjoiYnNwd2Vic2l0ZW1hcHMiLCJhIjoiY205czhoaHZsMDA2aTJscXBrMDl1ejNkcCJ9.cNaoijfQFmheUzrAeb1Eug';
		self.map = new mapboxgl.Map({
			container: 'map',
			style: 'mapbox://styles/mapbox/streets-v11',
			center: [147.1803, -9.4438],
			zoom: 12
		});

		self.map.on('load', function () {
			self.map.addSource('locations', {
				type: 'geojson',
				data: self.getGeoJSON(),
				cluster: true,
				clusterMaxZoom: 14,
				clusterRadius: 50,
			});
			self.renderClusters();
			self.setupMapFunctions();
		});

		self.map.on('style.load', function () {
			Object.keys(self.icons).forEach(function (key) {
				self.map.loadImage(self.icons[key], function (error, image) {
					if (!error) {
						self.map.addImage(key, image);
					}
				});
			});
		});
	};

	this.loadCountriesAndTypes = function () {
		this.countries = this.countries || [];
		this.locationTypes = this.locationTypes || [];

		for (let i = 0; i < this.data.length; i++) {
			let country = this.data[i].country;
			var type = this.data[i].type;

			//Add country to select
			if (!this.countries.includes(country)) {
				this.countries.push(country);

				const option = document.createElement('option');
				option.value = country;
				option.textContent = country;
				if (country == this.default_country)
					option.selected = true;

				this.location.appendChild(option);
			}

			//Add location type to nav
			if (!this.locationTypes.includes(type)) {
				this.locationTypes.push(type);

				const locationOpt = document.createElement('button');
				locationOpt.setAttribute('data-value', type);
				locationOpt.innerHTML = type;
				locationOpt.innerHTML += this.svg;

				this.resultNav.appendChild(locationOpt);
			}
		}
	}

	this.getGeoJSON = function () {
		let geojson = {
			type: "FeatureCollection",
			features: []
		};
		self.data.forEach(function (loc) {
			if (loc.latitude != '' && loc.longitude != '') {
				geojson.features.push({
					type: "Feature",
					properties: {
						id: loc.id,
						name: loc.name,
						type: loc.type,
						street1: loc.street1,
						suburb: loc.suburb,
						state: loc.state,
						phone: loc.phone,
						email: loc.email,
						hours: loc.hours,
						features: loc.features,
						location: loc.location,
					},
					geometry: {
						type: "Point",
						coordinates: [parseFloat(loc.longitude), parseFloat(loc.latitude)]
					}
				});
			}
		});
		return geojson;
	};

	this.renderClusters = function () {
		self.map.addLayer({
			id: 'clusters',
			type: 'circle',
			source: 'locations',
			filter: ['has', 'point_count'],
			paint: {
				'circle-color': '#FFFFFF',
				'circle-radius': ['step', ['get', 'point_count'], 20, 5, 30, 10, 40],
				'circle-stroke-color': '#18AA3D',
				'circle-stroke-width': 3
			}
		});

		self.map.addLayer({
			id: 'cluster-count',
			type: 'symbol',
			source: 'locations',
			filter: ['has', 'point_count'],
			layout: {
				'text-field': '{point_count_abbreviated}',
				'text-font': ['Montserrat Regular', 'Arial Unicode MS Bold'],
				'text-size': 18,
			},
			paint: {
				'text-color': '#24523B'
			}
		});

		// Layer for non-Branch markers
		self.map.addLayer({
			id: 'unclustered-point-other',
			type: 'symbol',
			source: 'locations',
			filter: ['all',
				['!', ['has', 'point_count']],
				['!=', ['get', 'type'], 'Branch']
			],
			layout: {
				'icon-image': ['case',
					['==', ['get', 'type'], 'ATM'], 'atm',
					['==', ['get', 'type'], 'Agency'], 'mobile',
					'marker-15'
				],
				'icon-size': 0.75,
				'text-offset': [0, 1.2],
				'text-anchor': 'top'
			}
		});

		// For the 'unclustered-point-other' layer
		self.map.on('mouseenter', 'unclustered-point-other', () => {
			self.map.getCanvas().style.cursor = 'pointer';

		});
		self.map.on('mouseleave', 'unclustered-point-other', () => {
			self.map.getCanvas().style.cursor = '';

		});

		// Layer for Branch markers (drawn on top)
		self.map.addLayer({
			id: 'unclustered-point-branch',
			type: 'symbol',
			source: 'locations',
			filter: ['all',
				['!', ['has', 'point_count']],
				['==', ['get', 'type'], 'Branch']
			],
			layout: {
				'icon-image': 'bank',
				'icon-size': 0.75,
				'text-offset': [0, 1.2],
				'text-anchor': 'top'
			},
			paint: {
				'icon-opacity': 1, // set icon opacity to 80%
				'text-opacity': 1  // set text opacity to 80%
			}
		});

		// For the 'unclustered-point-branch' layer
		self.map.on('mouseenter', 'unclustered-point-branch', () => {
			self.map.getCanvas().style.cursor = 'pointer';
		});
		self.map.on('mouseleave', 'unclustered-point-branch', () => {
			self.map.getCanvas().style.cursor = '';
		});

		self.map.on('click', 'clusters', function (e) {
			const features = self.map.queryRenderedFeatures(e.point, {
				layers: ['clusters']
			});
			if (!features.length) return;
			const clusterId = features[0].properties.cluster_id;
			self.map.getSource('locations').getClusterLeaves(clusterId, 100, 0, function (err, leaves) {
				console.log("Number of leaves:", leaves);
			});
		});
	};



	//This is to filter All/ATM/BRANCH....
	this.setupFilterByType = function () {
		var buttons = this.resultNav.querySelectorAll("button");
		buttons[0].classList.add('active');
		buttons.forEach(function (button) {
			button.addEventListener("click", function (event) {
				buttons.forEach(function (button) {
					button.classList.remove('active');
				});
				button.classList.add('active');
				self.filterLocationsByType(event.target.dataset.value);
			});
		});
	}

	//This is to filter by country
	this.setupFilterByCountry = function () {
		this.location.addEventListener("change", function (event) {
			var buttons = self.resultNav.querySelectorAll("button");
			buttons.forEach(function (button) {
				button.classList.remove('active');
			});
			buttons[0].classList.add('active');
			self.filterLocationsByType("all");
		});
	}

	//This is to search by keywords
	this.setupSearchByKeywords = function () {
		self.keywords.addEventListener('blur', function () {
			setTimeout(function () {
				self.autoComplete_list.style.display = "none";
			}, 200);
		});
		self.keywords.addEventListener("input", function () {
			var inputValue = self.keywords.value;
			const access_token = 'pk.eyJ1IjoiYnNwd2Vic2l0ZW1hcHMiLCJhIjoiY205czhoaHZsMDA2aTJscXBrMDl1ejNkcCJ9.cNaoijfQFmheUzrAeb1Eug';
			fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/${inputValue}.json?country=CK,FJ,PG,WS,SB,TO,VU&access_token=${access_token}`)
				.then(response => {
					if (!response.ok) {
						if (response.status === 400) {
							throw new Error('Bad Request (400)');
						}
						throw new Error(`HTTP error! Status: ${response.status}`);
					}
					return response.json();
				})
				.then(data => {
					var response = data;
					if (!response.features) {
						self.autoComplete_list.innerHTML = "";
						self.autoComplete_list.style.display = "";
						return;
					}

					var autocompleteItems = response.features.map(function (feature) {
						let country = "all";
						if (feature.context)
							country = feature.context.find(ctx => ctx.id.startsWith("country")).text;

						return {
							place_name: feature.place_name,
							country: country,
							geometry: feature.geometry.coordinates
						};
					});

					if (response.features[0] === undefined) {
						self.autoComplete_list.innerHTML = `<li rel=disabled>Sorry, there is no result with keyword "${inputValue}"</li>`;
						self.autoComplete_list.style.display = "block";

						return;
					}

					self.autoComplete_list.innerHTML = "";
					self.autoComplete_list.style.display = "block";

					autocompleteItems.forEach(function (item) {
						var listItem = document.createElement("li");
						listItem.textContent = item.place_name;

						listItem.setAttribute("data-country", item.country);
						listItem.setAttribute("data-coordinates", JSON.stringify(item.geometry));

						self.autoComplete_list.appendChild(listItem);
						listItem.addEventListener("click", function () {
							const country = listItem.getAttribute("data-country");
							const coordinates = JSON.parse(listItem.getAttribute('data-coordinates'));

							self.keywords.value = item.place_name;
							self.autoComplete_list.innerHTML = "";
							self.autoComplete_list.style.display = "none";

							self.location.value = country;
							if (coordinates) {
								self.filterLocationsByType("all");
								self.move_map_to(coordinates, 12, 500);
							}
						});
					});
				})
		});
	}

	this.setupBtnNearBy = function () {
		this.btnNearBy.addEventListener("click", function () {
			if (navigator.geolocation) {
				navigator.geolocation.getCurrentPosition(function (position) {
					let locations = self.data;

					locations.forEach(function (location) {
						location.distance = Math.sqrt(
							Math.pow(location.longitude - position.coords.longitude, 2) +
							Math.pow(location.latitude - position.coords.latitude, 2)
						);
					});

					locations.sort(function (a, b) {
						return a.distance - b.distance;
					});

					locations = locations.slice(0, 5); //5 for now
					self.updateMapLocations(locations);
					self.updateMapListings(locations);
					self.currentListing = locations;

					if (locations.length == 0) {
						self.resultWrapper.innerHTML = "<li><article>No locations found</article></li>";
						return;
					}

					self.location.value = "all";
					var buttons = self.resultNav.querySelectorAll("button");
					buttons.forEach(function (button) {
						button.classList.remove('active');
					});
					buttons[0].classList.add('active');

					const firstCoords = self.getFirstCoords(locations);
					self.move_map_to(firstCoords, 12, 500);
				});
			}
		});
	}

	//This is open the detail from the listing
	this.setupListingDetail = function () {
		const buttons = this.resultWrapper.querySelectorAll("button");
		buttons.forEach(function (button) {
			button.addEventListener("click", function (event) {
				const index = event.target.closest('li').dataset.index;
				const location = self.currentListing[index];
				const coordinates = [parseFloat(location.longitude), parseFloat(location.latitude)];
				self.showLocationDetail(location, coordinates);
			});
		});

		const headings = this.resultWrapper.querySelectorAll("h2");
		headings.forEach(function (button) {
			button.addEventListener("click", function (event) {
				const index = event.target.closest('li').dataset.index;
				const location = self.currentListing[index];
				const coordinates = [parseFloat(location.longitude), parseFloat(location.latitude)];
				self.showLocationDetail(location, coordinates);
			});
		});
	}
	//This is to filter by type (nav)
	this.filterLocationsByType = function (type) {
		if (!self.map.getSource('locations'))
			return;

		this.detailsWrapper.style.display = "none";
		var selectedCountry = self.location.value;
		var locations = self.data;

		if (selectedCountry !== "all") {
			locations = locations.filter(function (location) {
				return location.country == selectedCountry;
			});
		}

		if (type !== "all") {
			locations = locations.filter(function (location) {
				return location.type == type;
			});
		}

		self.updateMapLocations(locations);
		self.updateMapListings(locations);
		self.currentListing = locations;

		if (locations.length == 0) {
			self.resultWrapper.innerHTML = "<li><article>No locations found</article></li>";
			return;
		}

		const firstCoords = self.getFirstCoords(locations);
		const fullMap = [172, -10];

		const mapCoord = selectedCountry == "all" ? fullMap : firstCoords;
		let mapZoom = selectedCountry == "all" ? 3 : 12;
		if (selectedCountry == "all") {
			const screenWidth = window.innerWidth;
			if (screenWidth > 1024 && screenWidth <= 1260)
				mapZoom = 2.5;
			if (screenWidth <= 1024)
				mapZoom = 2;
		}
		self.move_map_to(mapCoord, mapZoom, 500);
	};

	//Clicked on the numbers to zoom in.
	self.setupClusterClicked = function (map) {
		map.on("click", "clusters", function (e) {
			var features = map.queryRenderedFeatures(e.point, {
				layers: ["clusters"],
			});

			var coordinates = features[0].geometry.coordinates;
			self.move_map_to(coordinates, map.getZoom() + 2, 500);
		});
	};

	//Clicked on the icons to open detail.
	self.setupUnclusterClicked = function (map) {
		map.on("click", ["unclustered-point-other", "unclustered-point-branch"], function (e) {
			const clicked_el = e.features[0];

			let location = clicked_el.properties;
			let coordinates = clicked_el.geometry.coordinates;
			self.showLocationDetail(location, coordinates);
		});
	};

	self.showLocationDetail = function (location, coordinates) {
		let item = document.querySelector('script[rel=CBMultipinMapListingItemDetail]').innerHTML;
		item = self.replaceTemplatePlaceholder(item, location);
		if (item) {
			self.detailsWrapper.style.display = "flex";
			self.detailsWrapper.innerHTML = item;
			if (coordinates[0] && coordinates[1]) {
				self.move_map_to(coordinates, 16, 500);
			}
		}
	}

	self.updateMapLocations = function (locations) {
		self.map.getSource('locations').setData({
			type: "FeatureCollection",
			features: locations.map(function (location, index) {
				return {
					type: "Feature",
					properties: { ...location, index: index },
					geometry: {
						type: "Point",
						coordinates: [parseFloat(location.longitude), parseFloat(location.latitude)]
					}
				};
			})
		});
	}

	self.updateMapListings = function (locations) {
		this.resultWrapper.innerHTML = "";
		const template = document.querySelector('script[rel=CBMultipinMapListingItem]').innerHTML;

		locations.forEach((location, index) => {
			if (location.longitude === "" || location.latitude === "")
				return;
			let item = template;
			item = self.replaceTemplatePlaceholder(item, location);
			item = item.replace(/{index}/g, index);
			this.resultWrapper.insertAdjacentHTML('beforeend', item);
		});
		self.setupListingDetail();
	}

	self.replaceTemplatePlaceholder = function (item, location) {
		switch (location.type) {
			case 'ATM':
				item = item.replace(/{type_svg}/g, self.iconATM);
				break;
			case 'Branch':
				item = item.replace(/{type_svg}/g, self.iconBranch);
				break;
		}
		item = item.replace(/{name}/g, location.name);
		item = item.replace(/{type}/g, location.type);
		item = item.replace(/{address}/g, self.generate_address(location.street1, location.suburb, location.state, location.postcode, location.country));
		item = item.replace(/{hours}/g, location.hours != "" ? `<p><strong>Hours:</strong><br/>${location.hours}</p>` : "");
		item = item.replace(/{features}/g, location.features != "" ? `<p><strong>This facility has:</strong><br/>${location.features}</p>` : "");
		item = item.replace(/{phone}/g, location.phone != "" ? `<p><strong>Phone:</strong>${location.phone}</p>` : "");
		item = item.replace(/{email}/g, location.email != "" ? `<p><strong>Email:</strong>${location.email}</p>` : "");

		return item;
	}

	self.generate_address = function (street, suburb, state, postcode, country) {
		let address = street == '' ? '' : `${street}, `;
		address += suburb == '' ? '' : `${suburb}`;
		address += (state == '' && suburb == '') ? '' : `,${state != '' ? ' ' + state : ''} ${postcode != '' ? ' ' + postcode : ''}`;
		address += country == '' ? '' : `, ${country}`;
		return `<p><strong>${address}</strong></p>`;
	}

	self.getFirstCoords = function (locations) {
		let firstCoords = [];
		for (const location of locations) {
			if (location.longitude === "" || location.latitude === "")
				continue;

			firstCoords = [parseFloat(location.longitude), parseFloat(location.latitude)];
			break;
		}

		return firstCoords;
	}

	self.move_map_to = function (location, zoom = 12, ease = 0) {
		self.map.easeTo({
			center: location,
			zoom: zoom,
			pitch: 0, // map is flat
			bearing: 0, // north is up
			duration: ease,
		});
		self.map.resize();
	};

	this.init();
};