<template>
	<div id="map-container" style="position: relative; height: 500px; width: 100%;">
		<v-progress-linear indeterminate v-if="loading"/>
		<div :id="props.shortcode ? 'map-shortcode' : 'map'"
			 style="height: 100%; width: 100%; position: relative;"></div>

		<v-sheet
			v-if="popupVisible"
			class="map-popup show"
			:style="{'bottom': props.isMobile ? '45px' : '5px'}"
			elevation="2"
			color="white"
		>
			<div class="popup-content d-flex flex-column">
				<v-btn
					icon="mdi-close"
					variant="text"
					size="x-small"
					@click="closePopup"
					class="close-popup"
				/>

				<div class="custom-hover" v-html="popupContent"></div>
			</div>
		</v-sheet>
	</div>
</template>

<script setup>
const {onMounted, watch, defineEmits, defineProps, ref} = Vue;

const props = defineProps({
	properties: {type: Array, default: () => []},
	shortcode: {type: Boolean, default: false},
	isMobile: {type: Boolean, default: false},
});

const emit = defineEmits(["zoom-change", "map-change"]);

let map = null;
let markersLayer = null;
const popupContent = ref("");
const popupVisible = ref(false);
const loading = ref(false)
let debounceTimer;
const locationDefault = {
	ne_lat: -0.8788717828324148,
	ne_lng: 184.21875000000003,
	sw_lat: -40.84706035607122,
	sw_lng: 84.02343750000001
}

const addMarkers = (properties) => {
	if (!map) return;

	if (markersLayer) {
		map.removeLayer(markersLayer);
	}
	markersLayer = L.layerGroup();

	const bounds = L.latLngBounds();

	properties.forEach((property) => {
		if (
			property.property_locations &&
			property.property_locations.latitude &&
			property.property_locations.longitude
		) {
			const customIcon = L.divIcon({
				className: "custom-marker",
				html: `<di class="text-center bg-white text-primary text-lg font-weight-bold rounded-pill pa-2 elevation-1">${money(property.property_pricings.base_price, property.properties.currency_code)}</di>`,
				iconSize: [100, 100],
				iconAnchor: [15, 30],
			});

			const marker = L.marker([property.property_locations.latitude, property.property_locations.longitude], {icon: customIcon});

			marker.on("click", () => {
				map.setView(
					[property.property_locations.latitude, property.property_locations.longitude],
					map.getZoom(),
					{
						animate: true,
					}
				);


				popupContent.value = `
					<a
						class="text-decoration-none text-black"
						href="${propertyLink(property)}"
					>
						<v-row
							class="d-flex align-items-center"
							style="height: ${props.isMobile ? '120px' : '150px'}; width: 100%;"
						>
							<v-col cols="${props.isMobile ? '4' : '6'}">
								<img
									src="${property.property_images[0]?.full_path_large ?? ''}"
									alt="${property.properties.name}"
									style="height: ${props.isMobile ? '100px' : '150px'}; border-radius: 8px; aspect-ratio: 16 / 9;"
								>
							</v-col>

							<v-col cols="${props.isMobile ? '8' : '6'}">
								<div class="pl-2">
									<span class="mb-2">${property.properties.name}</span>
									<p>From <strong>${money(property.property_pricings.base_price, property.properties.currency_code)}</strong> per night</p>
								</div>
							</v-col>
						</v-row>
					</a>
				`;
				popupVisible.value = true;
			});

			markersLayer.addLayer(marker);

			bounds.extend([
				property.property_locations.latitude,
				property.property_locations.longitude,
			]);
		}
	});

	markersLayer.addTo(map);

	if (bounds.isValid() && !props.shortcode) {
		map.fitBounds(bounds, {padding: [20, 20]});
	}
};

const handleMapChange = () => {
	if (loading.value || popupVisible.value) return
	clearTimeout(debounceTimer);

	debounceTimer = setTimeout(async () => {
		const {_northEast, _southWest} = map.getBounds();
		const location = {
			ne_lat: _northEast.lat,
			ne_lng: _northEast.lng,
			sw_lat: _southWest.lat,
			sw_lng: _southWest.lng
		}
		if (props.shortcode) {
			await load(location)
		}
	}, 1500)
};

const closePopup = () => {
	popupVisible.value = false;
	popupContent.value = "";
};

const propertyLink = (property) => {
	return `/${window.env.sas_route_vendor_property_main_featured}/${property.properties.id}/${property.properties.slug}`;
};

const load = async (location) => {
	try {
		loading.value = true;
		const params = {
			'search[ne_lat]': location.ne_lat,
			'search[ne_lng]': location.ne_lng,
			'search[sw_lat]': location.sw_lat,
			'search[sw_lng]': location.sw_lng,
			'search[show_boundary_results]': 1,
			per_page: 12,
			page: 1
		};
		const {data} = await axios.get("/properties/wordpress/search", {params});

		addMarkers(data.data.entities);
	} catch (e) {
		console.error(e);
	} finally {
		setTimeout(() => {
			loading.value = false;
		}, 1600);
	}
};


onMounted(async () => {
	const defaultCenter = [
		(locationDefault.ne_lat + locationDefault.sw_lat) / 2,
		(locationDefault.ne_lng + locationDefault.sw_lng) / 2,
	];
	const maxBounds = [
		[-90, -180],
		[90, 180],
	];
	map = L.map(props.shortcode ? 'map-shortcode' : 'map', {
		maxBounds: maxBounds,
		maxBoundsViscosity: 1.0,
		minZoom: 2,
		scrollWheelZoom: true,
		attributionControl: false,
	}).setView(defaultCenter, 4);

	L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(map);
	setTimeout(() => map.invalidateSize(), 0);

	if (props.shortcode) {
		await load(locationDefault)
	} else {
		addMarkers(props.properties);
	}

	map.on("moveend", handleMapChange);
});

watch(
	() => props.properties,
	(newProperties) => {
		addMarkers(newProperties);
	},
	{deep: true}
);
</script>

<style scoped>
.map-popup {
	position: absolute;
	left: 0;
	width: 100%;
	background: white;
	border-top-left-radius: 16px;
	border-top-right-radius: 16px;
	z-index: 1000;
	box-shadow: 0px -2px 8px rgba(0, 0, 0, 0.2);
	transition: transform 0.3s ease-in-out;
	transform: translateY(100%);
}

.map-popup.show {
	transform: translateY(0);
}

.popup-content {
	padding: 7px;
}

.close-popup {
	position: absolute;
	top: 8px;
	right: 8px;
}

.custom-hover:hover {
	text-decoration: underline;
}
</style>
