<!--
    
  Copyright (c) 2022 NIBIO <http://www.nibio.no/>. 
  
  This file is part of VIPSObservationApp.
  VIPSObservationApp is free software: you can redistribute it and/or modify
  it under the terms of the NIBIO Open Source License as published by 
  NIBIO, either version 1 of the License, or (at your option) any
  later version.
  
  VIPSObservationApp is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  NIBIO Open Source License for more details.
  
  You should have received a copy of the NIBIO Open Source License
  along with VIPSObservationApp.  If not, see <http://www.nibio.no/licenses/>.
    
  Author: Bhabesh Bhabani Mukhopadhyay
  Author: Tor-Einar Skog <tor-einar.skog@nibio.no>
  Dated : 19-Aug-2021
    
-->
<template>
	<div>
		<div id='map-observation'>
			<div v-if="isMyMapPanelVisible">
				<div v-if="isMapClicked">
					<div id="btnBack">
						<router-link id='btnBack_1'
							:to="{name: 'Observation', params:{observationId:myObservationId, paramGeoinfo:initGeoInfo, paramObservation:mapObservation }}"
							class="vips-btn">
							{{ $t("map.link.cancel.label") }} <i class="fas fa-times"></i>
						</router-link>
						&nbsp;
						<router-link id='btnBack_2'
							:to="{name: 'Observation', params:{observationId:myObservationId, paramGeoinfo:myGeoInfo, paramObservation:mapObservation}}"
							class="vips-btn">
							{{ $t("map.link.OK.label") }} <i class="fas fa-check"></i>
						</router-link>
					</div>
				</div>
				<div v-else>
					<router-link id='btnBack'
						:to="{name: 'Observation', params:{observationId:myObservationId, paramGeoinfo:myGeoInfo, paramObservation:mapObservation}}"
						class="vips-btn">
						{{ $t("map.link.back.label") }}
					</router-link>
				</div>
			</div>
			<div v-if="isMyMapPanelVisible" id='map-mylocation' style="margin: 5px;">
				<a v-on:click="myposition" style="cursor:pointer; ">
					<font-awesome-icon style="font-size: x-large; padding: 5px; color: white; background-color:#3d8052;"
						icon="location-crosshairs" /></a>
			</div>
		</div>



		<div id="ObservationMapPanel" v-if="isMyMapPanelVisible" ref='ObservationMapPanel'>
			<div>

				<select class="form-control" v-model="poi.pointOfInterestId" v-on:change="selectPOI($event)"
					ref="dropDownPOI">
					<option v-for="poi in lstPOI" v-bind:value="poi.pointOfInterestId">{{poi.name}}</option>
				</select>
				<div id="poiMarker">
					<img src="@/assets/map_icon.png">
				</div>

			</div>
		</div>
		<div v-else>
			<div id='divPrivacy' ref='divPrivacy' class="form-group">
				<visibility :locationIsPrivate="locationIsPrivate" :polygonService="polygonService"
					v-on:visibilityMapAction="visibilityMapAction" />
			</div>
		</div>
		<common-util ref="CommonUtil" />
	</div>
</template>

<script>
	import CommonUtil from '@/components/CommonUtil'
	import 'ol/ol.css';
	import Map from 'ol/Map';
	import OSM from 'ol/source/OSM';
	import TileLayer from 'ol/layer/Tile';
	import View from 'ol/View';
	import WMTS, {optionsFromCapabilities} from 'ol/source/WMTS';
	import WMTSCapabilities from 'ol/format/WMTSCapabilities';

	import {Vector as VectorSource} from 'ol/source';
	import {Vector as VectorLayer} from 'ol/layer';
	import Collection from 'ol/Collection';
	import {fromLonLat} from 'ol/proj';

	import Circle from 'ol/geom/Circle';
	import {Circle as CircleStyle, Fill, Stroke, Style, Icon} from 'ol/style';
	import Feature from 'ol/Feature';
	import GeoJSON from 'ol/format/GeoJSON';

	import {toStringXY} from 'ol/coordinate';
	import {transform} from 'ol/proj';
	import Point from 'ol/geom/Point';
	import {Modify} from 'ol/interaction';
	import Draw from 'ol/interaction/Draw';
	import Overlay from 'ol/Overlay';
	import Geolocation from 'ol/Geolocation';
	import Visibility from '@/components/Visibility'

	import i18n from '@/App'



	let parser = new WMTSCapabilities();


	export default {
		name: 'MapObservation',
		props: ['observationId', 'geoinfo', 'isMapPanelVisible', 'locationPointOfInterestId', 'locationIsPrivate', 'polygonService', 'observation'],
		components: {CommonUtil, Visibility},
		data() {
			return {
				CONST_URL_DOMAIN: '',
				isMyMapPanelVisible: '',
				myGeoInfo: '',
				initGeoInfo: '',
				latitude: 0,
				longitude: 0,
				mapZoom: 0,
				mapInteractions: '',
				lstPOI: [],
				poi: {pointOfInterestId: 'undefined', name: this.$i18n.t("mapobservation.label.selectPOI")},
				myMap: '',
				myObservationId: '',
				mapObservation: {},
				isMapClicked: false,
			}
		},
		methods: {
			visibilityMapAction(paramPrivate, paramPolygonService) {
				this.$emit('visibilityObservationAction', paramPrivate, paramPolygonService);
			},
			/** My current location */
			myposition() {
				let options = {enableHighAccuracy: true};
				navigator.geolocation.getCurrentPosition(this.geolocationSuccess, this.geolocationError, options);

			},
			/**
			 * Get GeoInfo
			 *  */
			geolocationSuccess(pos) {
				this.poi.pointOfInterestId = 'undefined';
				this.longitude = pos.coords.latitude;
				this.latitude = pos.coords.longitude;
				let coord = [pos.coords.longitude, pos.coords.latitude];
				let transFormCord = transform(coord, 'EPSG:3857', 'EPSG:4326');
				this.myMap.getView().setCenter(fromLonLat(coord));

				this.clearMapLayers();

				let myImage = this.myImage();

				let vectorSource = new VectorSource({});
				var iconFeature = new Feature({
					geometry: new Point(fromLonLat(coord))
				});

				vectorSource.addFeature(iconFeature);
				var vectorLayer = new VectorLayer({
					source: vectorSource,
					style: new Style({
						image: myImage,
					}),
				});



				let geoJSON = new GeoJSON();
				let resultGeoJSON = geoJSON.writeFeatures(vectorLayer.getSource().getFeatures());
				this.myGeoInfo = JSON.parse(resultGeoJSON);
				this.myGeoInfo.features[0].geometry.coordinates = coord;

				this.myMap.addLayer(vectorLayer);

				this.myMap.getView().setZoom(CommonUtil.CONST_GPS_OBSERVATION_ZOOM);

			},
			geolocationError(error) {
				console.log('geolocation error : ' + geolocationError);
			},

			/** Display of Map */
			initMap(myLatitude, myLongitude) {

				let pointOfInterestId = this.poi.pointOfInterestId;
				let This = this;
				let urlMap = CommonUtil.CONST_GPS_URL_NORWAY_MAP;    // Norway Map

				let myGeoInfo = this.myGeoInfo;
				let latitude = myLatitude;
				let longitude = myLongitude;
				let mapZoom = this.mapZoom;

				let image = this.myImage();


				let vectorSource = this.myVectorGeoSource();

				let vectorGeoLayer = this.myVectorGeoLayer(vectorSource, image);

				let mapInteractions = this.myInteractions(this.mapInteractions);

				let mapView = this.myView(latitude, longitude, mapZoom);


				let localIsMyMapPanelVisible = this.isMyMapPanelVisible;
				let coordinate = [latitude, longitude];

				let pointMarker = this.myOverLay(coordinate);
				let pointMarkerCoord = this.myOverLayCoord(latitude, longitude);

				/* Fetch Norway Map */

				fetch(urlMap)
					.then(function (response) {
						return response.text();
					})
					.then(function (text) {
						let parser = new WMTSCapabilities();
						let result = parser.read(text);

						let options = optionsFromCapabilities(result, {
							layer: 'topo4',
							matrixSet: 'EPSG:3857',
						});
						//console.info(options);
						// Need to force https on the tiles URL (bug in the service?)
						options.urls[0] = options.urls[0].replace("http","https");

						This.myMap = new Map({
							layers: [

								new TileLayer({
									opacity: 1,
									source: new WMTS(options),
								}),
								vectorGeoLayer

							],
							controls: [],
							interactions: mapInteractions,

							target: 'map-observation',
							view: mapView,
							overlays: [pointMarkerCoord],
							renderer: 'canvas',
						});



						/* On click event of map to get the location */
						This.myMap.on(['singleclick'], function (event) {
							if (localIsMyMapPanelVisible) {
								This.isMapClicked = true;

								This.poi.pointOfInterestId = 'undefined';

								let transFormCord = transform(event.coordinate, 'EPSG:3857', 'EPSG:4326');
								This.latitude = transFormCord[0];
								This.longitude = transFormCord[1];
								let mapNewCord = toStringXY(transform(event.coordinate, 'EPSG:3857', 'EPSG:4326'), 4);


								This.myMap.getView().setCenter(fromLonLat(transFormCord));

								/******* Below code for vector marker positioning */

								var iconFeature = new Feature({
									geometry: new Point(fromLonLat(transFormCord))
								});
								This.clearMapLayers();
								if (vectorSource) {}
								else {
									vectorSource = new VectorSource({});
								}

								if (vectorSource) {
									vectorSource.addFeature(iconFeature);

									var vectorLayer = new VectorLayer({
										source: vectorSource,
										style: new Style({
											image: image,
										}),
									});

									This.myMap.addLayer(vectorLayer);

									let geoGSON = new GeoJSON();
									let resultGeoGSON = geoGSON.writeFeatures(vectorLayer.getSource().getFeatures(), {
										dataProjection: 'EPSG:4326',
										featureProjection: 'EPSG:3857'
									});
									This.myGeoInfo = JSON.parse(resultGeoGSON);

								}
							}

						});

					})


			},


			myVectorGeoSource() {
				if (this.myGeoInfo) {
					return new VectorSource({
						features: new GeoJSON({
							dataProjection: "EPSG:4326",
							featureProjection: "EPSG:3857"
						}).readFeatures(this.myGeoInfo),
					})
				}
			},

			myVectorGeoLayer(vectorSource, image) {
				return new VectorLayer({
					source: vectorSource,
					style: new Style({
						image: image,
					}),
				})
			},
			myView(latitude, longitude, mapZoom) {
				return new View({
					center: fromLonLat([latitude, longitude]),
					zoom: mapZoom
				})
			},

			myImage() {
				var fill = new Fill({
					color: 'white'
				});

				return new CircleStyle({
					radius: 15,
					fill: fill,
					stroke: new Stroke({color: '#3d8052', width: 15}),
				});
			},


			myOverLay(coordinates) {
				return new Overlay({
					position: fromLonLat(coordinates),
					positioning: 'bottom-center',
					element: document.getElementById('poiMarker'),
					stopEvent: false
				});
			},


			myOverLayCoord(latitude, longitude) {
				let coordinate = [latitude, longitude];
				return this.myOverLay(coordinate);
			},


			myStyleFunction(styles, feature) {
				return styles[feature.getGeometry().getType()];
			},

			myInteractions(mapInteractions) {
				return (mapInteractions) ? [] : '';
			},

			/* Get point of interest */
			getMyPointOfInterst(lstPOI) {
				let userUUID = localStorage.getItem(CommonUtil.CONST_STORAGE_UUID);
				let jsonHeader = {Authorization: userUUID};

				lstPOI.push({pointOfInterestId: 'undefined', name: this.$i18n.t("mapobservation.label.noPOIselected")});

				fetch(this.CONST_URL_DOMAIN + CommonUtil.CONST_URL_USER_POI,
					{
						method: "GET",
						headers: jsonHeader,
					}).then((response) => {
						if (response.status == 200) {
							return response.json()
						}
					})
					.then((jsonLstPOI) => {
						$.each(jsonLstPOI, function (index, poi) {
							let myPOI = poi;
							lstPOI.push(myPOI);
						})

					})
			},

			/* Clear existing sources in map layers */
			clearMapLayers() {
				let myLayers = this.myMap.getLayers();
				if (myLayers) {
					this.myMap.getLayers().forEach(function (layer) {
						let source = layer.get('source');
						if (source) {
							source.clear();
						}

					})
				}
			},

			selectPOI(event) {
				let myPOI = this.poi;
				if (event.target.value != 0) {
					$.each(this.lstPOI, function (index, poi) {
						if (poi.pointOfInterestId === JSON.parse(event.target.value)) {
							myPOI = poi;
							return false;
						}
					})

					this.myGeoInfo = JSON.parse(myPOI.geoJSON);
					let coordinate = this.myGeoInfo.features[0].geometry.coordinates;
					this.latitude = coordinate[0];
					this.longitude = coordinate[1];



					let myImage = this.myImage();
					let transFormCord = [this.latitude, this.longitude];
					//let vectorSource        =   this.myVectorGeoSource();
					let vectorSource = new VectorSource({});

					var iconFeature = new Feature({
						geometry: new Point(fromLonLat(transFormCord))
					});

					vectorSource.addFeature(iconFeature);

					var vectorLayer = new VectorLayer({
						source: vectorSource,
						style: new Style({
							image: myImage,
						}),
					});

					this.clearMapLayers();
					this.myMap.addLayer(vectorLayer);

					this.myMap.getView().setCenter(fromLonLat(coordinate));
					this.myMap.getView().setZoom(CommonUtil.CONST_GPS_OBSERVATION_ZOOM);
				}



			}

		},
		mounted() {

			this.CONST_URL_DOMAIN = CommonUtil.CONST_URL_DOMAIN;
			this.latitude = CommonUtil.CONST_GPS_DEFAULT_LATITUDE_NORWAY;
			this.longitude = CommonUtil.CONST_GPS_DEFAULT_LONGITUDE_NORWAY;

			let routeParam = this.$route.params;

			// This ensures that the map fills the entire viewport
			var mapDiv = document.getElementById("map-observation");
			var navDiv = document.getElementById("vipsobsappmenu");
			var appDiv = document.getElementById("app");
			var panelObDiv = document.getElementById("ObservationMapPanel");
			var divPrivacy = document.getElementById("divPrivacy");

			if (routeParam.observation) {
				this.mapObservation = routeParam.observation;
			}

			if (routeParam.observationId) {
				this.myObservationId = routeParam.observationId;
			}
			if (this.observationId) {
				this.myObservationId = this.observationId;
			}

			if (routeParam.isMapPanelVisible) {
				this.isMyMapPanelVisible = routeParam.isMapPanelVisible;

			}
			if (this.isMapPanelVisible) {
				this.isMyMapPanelVisible = this.isMapPanelVisible;
			}

			if (this.isMyMapPanelVisible) {
				mapDiv.style.height = (screen.height - navDiv.offsetHeight) + "px";
				this.mapInteractions = '';

				appDiv.style.marginTop = "0";
				appDiv.style.paddingRight = "0";
				appDiv.style.paddingLeft = "0";

				this.getMyPointOfInterst(this.lstPOI);
			}
			else {
				mapDiv.style.height = 300 + "px";
				this.mapInteractions = 'interactions:[]';
			}

			if (routeParam.geoinfo) {
				this.myGeoInfo = routeParam.geoinfo;
				this.initGeoInfo = routeParam.geoinfo;

			}
			if (this.geoinfo) {
				this.myGeoInfo = this.geoinfo;
				this.initGeoInfo = this.geoinfo;
			}


			if (this.myGeoInfo) {
				this.latitude = this.myGeoInfo.features[0].geometry.coordinates[0];
				this.longitude = this.myGeoInfo.features[0].geometry.coordinates[1];
				this.mapZoom = CommonUtil.CONST_GPS_OBSERVATION_ZOOM;
			}
			else {
				this.mapZoom = CommonUtil.CONST_GPS_DEFAULT_ZOOM;
				//this.mapZoom = CommonUtil.CONST_GPS_OBSERVATION_ZOOM;
			}

			if (routeParam.locationPointOfInterestId) {
				this.poi.pointOfInterestId = routeParam.locationPointOfInterestId;
			}

			this.$nextTick(function () {
				this.initMap(this.latitude, this.longitude);
			});
		},
		beforeDestroy() {
			// This resets the container layout when leaving the router page
			var appDiv = document.getElementById("app");
			//appDiv.style.marginTop="60px";
			appDiv.style.paddingRight = "15px";
			appDiv.style.paddingLeft = "15px";
		},

	}
</script>

<style scoped>
	html,
	body,
	#map-observation {
		margin: 0;
		width: 100%;
	}

	#ObservationMapPanel {
		position: absolute;
		bottom: 0;
		left: 0;
	}

	#btnBack {
		position: fixed;
		z-index: 2000;
	}

	#map-mylocation {
		position: fixed;
		right: 0;
		z-index: 2000;
	}
</style>