<template>
	<v-menu v-model="menu" location="bottom">
		<template #activator="bind">
			<div>
				<v-autocomplete
					v-model="address"
					:items="addresses"
					:label="label"
					:loading="loadingAddresses"
					clearable
					hide-details
					item-title="formattedAddress"
					item-value="location"
					variant="solo"
					@update:model-value="(v) => osm.addressSelect(v)"
					@click:clear="osm.addressClear()"
				/>
			</div>
		</template>

		<v-card>
			<div class="d-flex flex-column" style="max-height:450px;">
				<div>
					<v-list>
						<v-list-subheader>
							<div class="d-flex align-center" style="gap:15px;">
								<img v-if="propsData.flag" :src="propsData.flag" alt="" height="20"/>
								<span>{{ propsData.formatted || 'Search Results' }}</span>
							</div>
						</v-list-subheader>
					</v-list>
				</div>

				<div v-if="osm.error.exists()">
					<v-alert rounded="0" type="error">Unable to geocoding</v-alert>
				</div>

				<!-- <div
					v-if="props.map"
					:style="[
					'min-height:'+ (osm.response.length==0 ? 300 : 200)+'px!important',
					'max-height:'+ (osm.response.length==0 ? 300 : 200)+'px!important',
					'transition: all 300ms ease;',
					'position: relative;',
				  ]"
				>
				  <l-map
					  ref="mapRef"
					  style="position:absolute; top:0; left:0; right:0; bottom:0; width:100%; height:100%;"
					  v-bind="map.bind"
					  @click="map.mapCLickHandler($event)"
				  >
					<l-tile-layer
						layer-type="base"
						name="OpenStreetMap"
						url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
					></l-tile-layer>
					<l-marker :latLng="map.bind.center" draggable @dragend="map.markerDragend($event)">
					  <l-icon icon-url="https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png"/>
					</l-marker>
				  </l-map>
				</div> -->
			</div>
		</v-card>
	</v-menu>
</template>

<script setup>
// import 'leaflet/dist/leaflet.css';
// import {LIcon, LMap, LMarker, LTileLayer} from '@vue-leaflet/vue-leaflet';
const {defineEmits, defineProps, onBeforeMount, reactive, ref, watch} = Vue;

const props = defineProps({
	formatted: {type: String, default: ''},
	suburb: {type: String, default: ''},
	city: {type: String, default: ''},
	state: {type: String, default: ''},
	country: {type: String, default: ''},
	address: {type: String, default: ''},
	country_code: {type: String, default: ''},
	postcode: {type: String, default: ''},
	state_code: {type: String, default: ''},
	map: {type: Boolean, default: true},
	label: {type: String, default: 'Destination'},
	errorMessage: {type: Boolean, default: false},
	ignore_bookings: {type: Number, default: 0},
	boundary: {type: Number, default: 0}
});

const emit = defineEmits([
	'update:formatted',
	'update:suburb',
	'update:city',
	'update:state',
	'update:country',
	'change',
	'address',
	'country_code',
	'postcode',
	'state_code',
	'blur',
	'ignore_bookings',
	'boundary'
]);

const mapRef = ref({});
const menu = ref(false)
const address = ref(null)
const addresses = ref([])
const loadingAddresses = ref(false)

onBeforeMount(async () => {
	osm.init();
	await mountAddress()

	address.value = {
		suburb: props.suburb,
		city: props.city,
		state: props.state,
		country: props.country,
		formattedAddress: props.formatted,
	};

	if (
		props.suburb === '' || props.suburb === null &&
		props.city === '' || props.city === null &&
		props.state === '' || props.state === null &&
		props.country === '' || props.country === null &&
		props.formatted === '' || props.formatted === null
	) {
		address.value = null;
	}

});

const mountAddress = async () => {
	try {
		loadingAddresses.value = true
		const {data} = await axios.get(`/vendor/vendor_group/list_locations`)
		addresses.value = data.data

		addresses.value = addresses.value.map(address => {
			return {
				location: address.location,
				formattedAddress: `${address.location.suburb}, ${address.location.state} - ${address.location.country}`
			}
		})
			.filter(address => address.location.suburb !== null)
	} catch (e) {
		console.log(e)
	} finally {
		loadingAddresses.value = false
	}
}

const osm = useAxios({
	params: lodash.merge({
		format: 'json',
		addressdetails: 1,
		extratags: 1,
		limit: 15,
	}, props.params),
	response: [],
	mapRef: {},
	onSuccess(response) {
		osm.response = response.data.map(addr => osm.addressDefault(addr));
		setTimeout(() => {
			mapRef.value.leafletObject.panTo(map.bind.center);
		}, 1000);
	},
	addressDefault(place = {}) {
		place = useOsmPlace(place);

		if (Object.values(mapRef.value ?? {}).length > 0) {
			const bounds = mapRef.value.leafletObject.getBounds();
			place.ne_lat = bounds._northEast.lat;
			place.ne_lng = bounds._northEast.lng;
			place.sw_lat = bounds._southWest.lat;
			place.sw_lng = bounds._southWest.lng;
		}

		return place;
	},
	async addressByCoords(lat, lng) {
		try {
			const {data} = await axios.get(`https://nominatim.openstreetmap.org/reverse?format=json&addressdetails=1&extratags=1&namedetails=1&lat=${lat}&lon=${lng}`);
			if (data.error) {
				console.log(data.error);
				return osm.error.setData(data.error);
			}
			osm.addressSelect(data);
		} catch (err) {
			console.error(err);
		}
	},
	addressClear() {
		menu.value = false
		address.value = null
		for (const attr in propsData.value) {
			propsData.value[attr] = null;
		}
	},
	async addressSelect(addr) {
		if (addr === null || addr === undefined) return
		addr = osm.addressDefault(addr);
		for (const name in addr) {
			propsData.value[name] = addr[name];
		}

		if (propsData.value.formatted) {
			osm.params.q = propsData.value.formatted
		}
		setTimeout(() => emit('blur'))
		map.bind.center = [addr.lat, addr.lng];
		menu.value = false
	},
	async init() {
		if (props.lat && props.lng) {
			osm.addressByCoords(props.lat, props.lng);
		}
	},
});

const propsData = ref(osm.addressDefault({
	formatted: props.formatted || null,
	suburb: props.suburb || null,
	city: props.city || null,
	state: props.state || null,
	country: props.country || null,
	country_code: props.country_code || null,
	postcode: props.postcode || null,
	state_code: props.state_code || null,
	address: props.address || null,
	boundary: props.boundary || null,
	ignore_bookings: props.ignore_bookings || null
}));

watch([propsData.value], ([propsDataNew]) => {
	emit('update:formatted', propsDataNew.formatted);
	emit('update:suburb', propsDataNew.suburb);
	emit('update:city', propsDataNew.city);
	emit('update:state', propsDataNew.state);
	emit('update:country', propsDataNew.country);
	emit('change', propsDataNew);

	emit('update:address', propsDataNew.address);
	emit('update:postcode', propsDataNew.postcode);
	emit('update:state_code', propsDataNew.state_code);
	emit('update:country_code', propsDataNew.country_code);
	emit('update:boundary', propsDataNew.boundary);
	emit('update:ignore_bookings', propsDataNew.ignore_bookings);
});

const map = reactive({
	bind: {
		zoom: 12,
		center: [
			parseFloat(propsData.value.lat),
			parseFloat(propsData.value.lng),
		],
		useGlobalLeaflet: false,
		options: {},
	},
	async markerDragend($event) {
		const coords = $event.target.getLatLng();
		map.bind.center = [coords.lat, coords.lng];
		await osm.addressByCoords(coords.lat, coords.lng);
	},
	async mapCLickHandler($event) {
		map.bind.center = [$event.latlng.lat, $event.latlng.lng];
		await osm.addressByCoords($event.latlng.lat, $event.latlng.lng);
	},
});

const slotBind = () => {
	return {
		...osm,
	};
};
</script>
