<template>
	<div class="vue-component items">
		<SearchableList
			:data="data"
			summaryKey="title"
			:showSummaryOnExpand="false"
			:externalSearchTerm="searchTerm"
			:externalHideDeprecated="hideDeprecated"
			:deprecatedFilter="deprecatedFilter"
			:externalHideExperimental="hideExperimental"
			:experimentalFilter="experimentalFilter"
			:sort="sort"
			:offerDetails="offerDetails"
			:heading="heading"
			:collapsed="collapsed"
			:loadAdditionalData="loadAdditionalData"
			@summaries="updateFeatures"
			@detailsToggled="detailsToggled"
			ref="list">
			<template #heading="scope"><slot name="heading" v-bind="scope" /></template>
			<template #content-start="scope"><slot name="content-start" v-bind="scope"></slot></template>
			<template #after-search-box="scope">
				<slot v-if="showMap" name="map" :geojson="geojson" :mapOptions="mapOptions">
					<div class="map overview" ref="mapContainer"></div>
				</slot>
				<slot name="after-search-box" v-bind="scope"></slot>
			</template>
			<template #summary="scope"><slot name="summary" v-bind="scope" /></template>
			<template #details="slot">
				<Item :data="slot.item" :mapOptions="mapOptions">
					<template #title><span class="hidden" /></template>
					<template #before-description="scope"><slot name="item-before-description" v-bind="scope" /></template>
					<template #end="scope"><slot name="item-end" v-bind="scope" /></template>
					<template #location="scope"><slot name="item-location" v-bind="scope" /></template>
				</Item>
			</template>
		</SearchableList>
	</div>
</template>

<script>
import Utils from '../utils';
import MapMixin from './internal/MapMixin';
import FederationMixin from './internal/FederationMixin';

const geoJsonStyle = {
	color: '#3388ff',
	fillOpacity: 0.2
};

export default {
	name: 'Items',
	mixins: [
		FederationMixin,
		MapMixin
	],
	components: {
		Item: () => Utils.loadAsyncComponent(import('./Item.vue')),
		SearchableList: () => Utils.loadAsyncComponent(import('./SearchableList.vue'))
	},
	props: {
		items: {
			type: [Array, Object], // Either a GeoJSON FeatureCollection or an array of Items
			default: () => ([])
		},
		showMap: {
			type: Boolean,
			default: false
		},
		searchTerm: {
			type: String,
			default: null
		},
		sort: {
			type: Boolean,
			default: true
		},
		offerDetails: {
			type: Boolean,
			default: true
		},
		heading: {
			type: String,
			default: 'Items'
		},
		collapsed: {
			type: Boolean,
			default: null
		},
		hideDeprecated: {
			type: Boolean,
			default: false
		},
		deprecatedFilter: {
			type: Boolean,
			default: false
		},
		hideExperimental: {
			type: Boolean,
			default: false
		},
		experimentalFilter: {
			type: Boolean,
			default: false
		},
		loadAdditionalData: {
			type: Function,
			default: null
		},
		missing: {
			type: Array,
			default: null
		},
		...FederationMixin.props,
		...MapMixin.props,
	},
	data() {
		return {
			summaries: []
		};
	},
	computed: {
		data() {
			if (Array.isArray(this.items)) {
				return this.items;
			}
			else if (Utils.isObject(this.items) && this.items.type === 'FeatureCollection' && Array.isArray(this.items.features)) {
				return this.items.features;
			}
			else {
				return [];
			}
		},
		geojson() {
			let geojson = {
				type: "FeatureCollection",
				features: []
			}
			for(let summary of this.summaries) {
				if (!summary.show) {
					continue;
				}
				geojson.features.push(this.data[summary.index]);
			}
			return geojson;
		}
	},
	watch: {
		geojson() {
			if (!this.map) {
				this.initMap();
			}
			else {
				this.setFeatures();
			}
		}
	},
	methods: {
		updateFeatures(summaries) {
			this.summaries = summaries;
		},
		addFeatures() {
			this.setFeatures(false);
			return this.map.geometries;
		},
		setFeatures(addToMap = true) {
			if (!this.map || !this.map.instance) {
				return;
			}
			if (this.map.geometries) {
				this.map.geometries.remove();
			}

			let geom = this.map.leaflet.geoJSON(this.geojson, {
				style: geoJsonStyle
			});
			geom.on('click', e => {
  				var pt = this.map.leaflet.latLngBounds(e.latlng, e.latlng);
				geom.eachLayer(layer => {
					let bounds = layer.getBounds();
					let index = this.summaries.findIndex(d => d.identifier === layer.feature.id);
					this.$refs.list.toggleDetails(index, pt.intersects(bounds));
				});
			});
			if (addToMap) {
				geom.addTo(this.map.instance);
			}
			this.map.geometries = geom;
		},
		detailsToggled(...args) {
			this.$emit('detailsToggled', ...args);
		}
	}
}
</script>

<style lang="scss">
@use './base.scss';

.vue-component.items {
	.map.overview {
		margin-bottom: 1em;
	}
}
</style>