/* Minification failed. Returning unminified contents.
(64,7): run-time error JS1004: Expected ';'
(73,26): run-time error JS1004: Expected ';'
(74,9): run-time error JS1004: Expected ';'
(319,7): run-time error JS1004: Expected ';'
(323,24): run-time error JS1004: Expected ';'
(350,48-56): run-time error JS1006: Expected ')': function
(350,59): run-time error JS1004: Expected ';'
(362,9): run-time error JS1004: Expected ';'
(374,3-4): run-time error JS1195: Expected expression: )
 */
/**
 * A module that provides helper functions for working with location data.
 *
 * @namespace locationHelpers
 */
const locationHelpers = (function () {
	const GRANULARITY_LEVEL = {
		COARSE: 1,
		FINE: 2,
		USER_ENTERED: 3,
	};

    const LOCATION_COOKIE_NAME = ws.userLocationCookieName;

	function getCurrentPosition(handleLocationError) {
		return new Promise((resolve, reject) => {
			if (!navigator.geolocation) {
				reject(new Error('Geolocation is not supported by this browser.'));
			} else {
				navigator.geolocation.getCurrentPosition(
					(position) => {
						resolve(position);
					},
					(error) => {
						if (handleLocationError) {
							handleLocationError(error);
						}
						reject(error);
					}
				);
			}
		});
	}

	/**
	 * Updates the user's location.
	 * @param {Object} location - The location object containing latitude and longitude.
	 * @returns {Promise} - A promise that resolves with the response data.
	 */
	function updateUserLocation(location) {
		ws.loadingStart();

		return $.ajax({
			url: '/UpdateUserLocation',
			method: 'POST',
			contentType: 'application/json',
			data: JSON.stringify(location),
		})
			.done(function (data) {
				return data;
			})
			.fail(function (jqXHR, textStatus, error) {
				console.error('Error setting zip from latitude and longitude: ', error);
			})
			.always(function () {
				ws.loadingStop();
			});
	}

	/**
	 * Determines the user's location and updates it if necessary.
	 * @returns {Promise<void>} A promise that resolves when the location is determined and updated.
	 */
	async function determineLocation() {
		try {
			const existingLocation = getCookie(LOCATION_COOKIE_NAME);

			if (existingLocation && existingLocation.GranularityLevel !== GRANULARITY_LEVEL.COARSE) {
				return;
			}

			const ZIPCODE_COOKIE_NAME = ws.userZipCodeCookieName;
			const position = await getCurrentPosition(handleLocationError);
			await showPosition(position);

			const location = {
				Latitude: position.coords.latitude,
				Longitude: position.coords.longitude,
				GranularityLevel: GRANULARITY_LEVEL.FINE,
				Zip: getCookie(ZIPCODE_COOKIE_NAME)
			};

			setCookie(LOCATION_COOKIE_NAME, location, 1);

			return updateUserLocation(location);
		} catch (error) {
			console.error("locationHelper: Error determining location:", error);
		}
	}

	function showPosition(position) {
		return new Promise((resolve, reject) => {
			const ZIPCODE_COOKIE_NAME = ws.userZipCodeCookieName;
			const GEOAPIKEY = ws.googleGeoCodeApiKey;

			const lat = position.coords.latitude;
			const lng = position.coords.longitude;
			const latlng = { lat, lng };

			const zipCode = getCookie(ZIPCODE_COOKIE_NAME);

			if (zipCode) {
				resolve(position);
				return;
			}

			if (!GEOAPIKEY) {
				resolve(position);
				return;
			}

			var geocoder = new google.maps.Geocoder();

			geocodeLocation(geocoder, latlng)
				.then((results) => {
					const validResults = results.filter(result =>
						result.address_components.find(x => x.types.includes("postal_code"))
					);

					if (Array.isArray(validResults) && validResults.length > 0) {
						const zipCode = validResults[0].address_components.find(x => x.types.includes("postal_code"));

						if (zipCode) {
							setCookie("zip_address", zipCode.short_name, 1);
						}
						resolve(position);
					} else {
						console.error('locationHelper: No results found');
						resolve(position);
					}
				})
				.catch((error) => {
					console.error('locationHelper: Geocoder failed due to: ', error);
					reject(error);
				});
		});
	}

	function geocodeLocation(geocoder, latlng) {
		return new Promise((resolve, reject) => {
			geocoder.geocode({ 'location': latlng }, (results, status) => {
				if (status === 'OK') {
					resolve(results);
				} else {
					reject(status);
				}
			});
		});
	}
	
	function handleLocationError(error) {
		switch (error.code) {
			case error.PERMISSION_DENIED:
				console.info('Opted out of geolocation request.');
				break;
			case error.POSITION_UNAVAILABLE:
				console.warn('Geolocation information is unavailable.');
				break;
			case error.TIMEOUT:
				console.error('Geolocation request timed out.');
				break;
			case error.UNKNOWN_ERROR:
				console.error('An unknown error occurred with the geolocation request.');
				break;
			default:
				console.error('An error occurred with geolocation request: ', error);
				break;
		}
	}

	return {
		determineLocation,
	};
})();
;
const storeLocator = (function () {
	let _closetStore;
	const STORE_NAME_DATA = 'store-name';
	const CLOSING_TIME_DATA = 'store-closing-time';
	const OPENING_TIME_DATA = 'store-opening-time';
	const SET_CLOSEST_STORE_URL = '/SetClosestStore';

	const $storeSelectionListSideMenu = $('.store_selection_list_side_menu');
	const $currentStoreClosingTime = $('.currentStoreClosingTime');

	function showStoreLocationsMenu() {
		if (!_closetStore) {
			zip.storeLocatorZipModal(function (closestStore) {
				_closetStore = closestStore;

				addClosestStoreIndicator(_closetStore);

				const $store = $(`[data-store-name='${_closetStore}']`);
				const closingTime = $store.data(CLOSING_TIME_DATA);
				const openingTime = $store.data(OPENING_TIME_DATA);

				setCurrentStore(_closetStore);
				setOperationalHours(openingTime, closingTime);
			});
		}

		$storeSelectionListSideMenu.addClass('open');
	}

	function addClosestStoreIndicator(closestStoreName = '') {
		closestStoreName = closestStoreName.replaceAll(' ', '');

		$('.closest-indicator').css('visibility', 'hidden');
		$('.store').css('order', '0');

		$(`.${closestStoreName} .closest-indicator`).css('visibility', 'visible');
		$(`.store.${closestStoreName}`).css('order', '-1');

		$('.state-store-container').css('order', '0');

		$(`.${closestStoreName}`).closest('.state-store-container').css('order', '-1');
	}

	function hideStoreLocationsMenu() {
		$storeSelectionListSideMenu.removeClass('open');
	}

	/**
	 * Sets the operational hours of a store.
	 *
	 * @param {string} openingTime - The opening time in 12-hour format (e.g., "8AM", "8:30AM").
	 * @param {string} closingTime - The closing time in 12-hour format (e.g., "5PM", "5:30PM").
	 */
	function setOperationalHours(openingTime = '', closingTime = '') {
		const currentHour = getCurrentTime24HourFormat();

		const openingHour = convertTimeTo24HourFormat(openingTime);
		const closingHour = convertTimeTo24HourFormat(closingTime);

		if (!openingHour || !closingHour) {
			console.error('Invalid opening or closing time');
			return;
		}

		const timezone = !isUserInCentralTimezone() ? ' CST' : ""

		if (currentHour < openingHour) {
			$currentStoreClosingTime.text(`(opens at ${openingTime}${timezone})`);
		} else if (currentHour < closingHour) {
			$currentStoreClosingTime.text(`(closes at ${closingTime}${timezone})`);
		} else {
			$currentStoreClosingTime.text(`(closed, opens at ${openingTime} tomorrow)`);
		}
	}

	function isUserInCentralTimezone() {
		const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
		return userTimezone === 'America/Chicago';
	}

	/**
	 * Converts a time string from 12-hour format to 24-hour format.
	 *
	 * @param {string} time - The time string in 12-hour format (e.g., "1PM", "12:30AM").
	 * @returns {string} The time string in 24-hour format (e.g., "1300", "0030").
	 * @throws {Error} Throws an error if the input time string is not in valid 12-hour format.
	 */
	function convertTimeTo24HourFormat(time) {
		const period = time.slice(-2).toLowerCase();
		const [hourString, minutes = '00'] = time.slice(0, -2).split(':');
		let hour = parseInt(hourString, 10);

		if (isNaN(hour) || hour < 1 || hour > 12 || (period !== 'am' && period !== 'pm')) {
			throw new Error('Invalid time format');
		}

		if (period === 'pm' && hour < 12) {
			hour += 12;
		} else if (period === 'am' && hour === 12) {
			hour = 0;
		}

		return hour.toString().padStart(2, '0') + minutes;
	}

	/**
	 * Gets the current time and formats it in 24-hour format.
	 *
	 * @returns {string} The current time in 24-hour format (e.g., "2030" for 8:30 PM).
	 */
	function getCurrentTime24HourFormat() {
		const now = new Date();
		const hour = now.getHours();
		const minutes = now.getMinutes();
		return hour.toString().padStart(2, '0') + minutes.toString().padStart(2, '0');
	}

	function setCurrentStore(currentStore) {
		if (currentStore) {
			$('.currentStore').text(currentStore);
		} else {
			$('.currentStore').text('Nearest store');
		}
	}

	function getLocation(closestStore) {
		if (!closestStore) {
			setUserLocation();
		} else {
			_closetStore = closestStore;

			addClosestStoreIndicator(_closetStore);

			const $store = $(`.${_closetStore} .address-row`);
			const storeName = $store.data(STORE_NAME_DATA);
			const closingTime = $store.data(CLOSING_TIME_DATA);
			const openingTime = $store.data(OPENING_TIME_DATA);

			setCurrentStore(storeName);
			setOperationalHours(openingTime, closingTime);
		}
	}

	async function setUserLocation() {
		let userLocation = getCookie(ws.userLocationCookieName);
		let zip = getCookie(ws.userZipCodeCookieName);
		if (!userLocation || !userLocation.Store) {
			userLocation = await locationHelpers.determineLocation();

			if (!userLocation || !userLocation.Store) {
				return;
			}
		}

		const store = userLocation.Store;

		_closetStore = store;

		addClosestStoreIndicator(_closetStore);

		const $store = $(`[data-store-name='${store}']`);
		const closingTime = $store.data(CLOSING_TIME_DATA);
		const openingTime = $store.data(OPENING_TIME_DATA);

		setCurrentStore(store);
		setOperationalHours(openingTime, closingTime);
	}

	$('body').append($storeSelectionListSideMenu);

	$('.store_selection_text').on('click', showStoreLocationsMenu);

	$('.store_selection_overlay, .close-store-selector-menu').on('click', hideStoreLocationsMenu);

	$(document).on('click', '.address-row', async function () {
		const $store = $(this);
		const storeName = $store.data(STORE_NAME_DATA);
		const closingTime = $store.data(CLOSING_TIME_DATA);
		const openingTime = $store.data(OPENING_TIME_DATA);

		setCurrentStore(storeName);
		setOperationalHours(openingTime, closingTime);
		addClosestStoreIndicator(storeName);
		hideStoreLocationsMenu();

		try {
			await ws.post(SET_CLOSEST_STORE_URL, { storeName });

			// Reload the page if the user is on a PLP
			const isOnPLP = location.pathname.includes(getCookieValue('Warners Stellian PLP cookie'))
			const isOnStoreLocationsPage = location.pathname.includes('store-locations')
			if (isOnPLP || isOnStoreLocationsPage) {
				location.reload();
			}

		} catch (error) {
			console.error('Error occurred while setting closest store: ', error);
		}
	});

	return {
		getLocation,
	};
})();
;
