<!--
    
  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>
				<router-link id='btnBack' :to="{name:'PlacesList', params: {}}" class="vips-btn">
				  {{ $t("map.link.back.label") }}
                </router-link>
			<div v-show="userCanEditPOI" 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 id='map-poi'></div>

            <div id='divPoiData' class="container" >
                <div class="form-group"><input class="form-control" :placeholder="$t('mapPOI.poiName.label')" id='poiName' ref='poiName' v-model="poi.name" :disabled="!userCanEditPOI"/></div>

                <div class='form-group'>
                        <select class="form-control" v-model="poi.pointOfInterestTypeId" :disabled="!userCanEditPOI">
                            <option v-for="poiType in poiTypes" v-bind:key="poiType.point_of_interest_type_id" :value='poiType.point_of_interest_type_id' :disabled="!poiType.is_user_selectable">{{$t(poiType.default_name)}}</option>
                        </select>
                </div>
				<div class="form-group" v-show="userCanEditPOI">
					<div class="float-right">
			          <a class="vips-btn" v-on:click="validate">{{$t("save.label")}}</a>
			          <a v-show="POIExists" class="vips-btn danger" v-on:click="callForRemovePOI">{{$t("delete.label")}}</a>
			        </div>
				</div>
            </div>
            <div id="poiMarker" style="display:none">
                <img src="@/assets/map_icon.png"> 
            </div>
		<sync ref="sync"/>
    </div>
</template>

<script>
import CommonUtil from '@/components/CommonUtil';
import Sync from '@/components/Sync'

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} 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 i18n from '@/App'


export default{
    name        :   'MapPOI',
    components  :   {Sync},
    props       :   ['pointOfInterestId'],

    data()      {
                    return {
                        poi                     :   {},
                        mapZoom                 :   0,
                        poiTypes                :   [],
                        msgErr                  :   '',
                        map                     :   '',
                        
                        
                    }
    },
	computed: {
		userCanEditPOI: function(){
			return this.isPOIOwnedByUser();
		},
		POIExists: function() {
			return this.poi.pointOfInterestId;
		}
	},
    methods :   {
	
		isPOIOwnedByUser(){
			return !this.poi.pointOfInterestId || (this.poi.userId && this.poi.userId == this.$root.sharedState.userId);
		},
                callForRemovePOI()
                {
					if(confirm(this.$i18n.t("mapPOI.modal.label.deleteprompt") + " " + this.poi.name + "?"))
					{
						this.deletePOI();
					}
                },
                deletePOI()
                {
                    if(this.poi.pointOfInterestId)
                    {
                        if(this.poi.pointOfInterestId < 0)
                        {
                             /** Just remove it locally */
                            this.removeLocalPOI(this.poi.pointOfInterestId);
                            this.$router.replace({path:'/places'});
                        }
                        else
                        {
                            /** Mark the record - for sending to server */
                            this.poi.deleted=true;
                            this.saveToStore();
                        }
                        
                    }
                },
                removeLocalPOI(id)
                {
                        let lstPOI = JSON.parse(localStorage.getItem(CommonUtil.CONST_STORAGE_POI_LIST));
                        let indexPosition       = null;
                        $.each(lstPOI, function(index, poi){
                            if(poi.pointOfInterestId===id)
                            {
                                indexPosition = index;
                                return false;
                            }
                        }); 

                        if(indexPosition)
                        {

                            lstPOI.splice(indexPosition,1);
                            localStorage.setItem(CommonUtil.CONST_STORAGE_POI_LIST,JSON.stringify(lstPOI));

                        }                        
                        
                },
                validate()
                {
                    if((!this.poi.name) || (this.trimString(this.poi.name) === '')) 
                    {
						alert(this.$i18n.t("mapPOI.modal.alert.missingPOIName"));
						return;
                    }
					if(!this.poi.geoJSON)
					{
						alert(this.$i18n.t("mapPOI.modal.alert.missingGeoInfo"));
						return;
					}

						// TODO Simplify this logic 
                    if (!this.poi.pointOfInterestTypeId)
                    {
                        if(this.poi.pointOfInterestTypeId === 0) 
                        {
                            // Pass
                        }
                        else
                        {
                        	alert(this.$i18n.t("mapPOI.modal.alert.missingPOIType"));
							return false;
                        }
                    }
                    
					if(confirm(this.$i18n.t("mapPOI.modal.label.saveprompt") + " " + this.poi.name + "?"))
					{
						this.saveToStore();
					}
                },        
                getPointOfInterest(id){
                    let lstPOI  =   JSON.parse(localStorage.getItem(CommonUtil.CONST_STORAGE_POI_LIST));
                    let poi     =   lstPOI.find(({pointOfInterestId}) => pointOfInterestId === id);
                    
                    this.poi    =   poi;

                },
                saveToStore(){
                    let This    =   this;
                    let lstPOI  =   JSON.parse(localStorage.getItem(CommonUtil.CONST_STORAGE_POI_LIST));
                    if(this.poi.pointOfInterestId)
                    {
                    $.each(lstPOI, function(index, poi){
                            if(poi.pointOfInterestId === This.poi.pointOfInterestId)
                            {
                                poi.latitude=This.poi.latitude;
                                poi.longitude=This.poi.longitude;
                                poi.name=This.poi.name;
                                poi.pointOfInterestTypeId=This.poi.pointOfInterestTypeId;
                                poi.geoJSON=This.poi.geoJSON
                                poi.uploaded=false;
                                if(This.poi.deleted)
                                {
                                    poi.deleted = This.poi.deleted;
                                }
                               
                            }
                    })
                    }
                    else
                    {
                        this.poi.pointOfInterestId = this.getNewPoiId(lstPOI);
						this.poi.userId = this.$root.sharedState.userId;
                        this.poi.uploaded=false;
                        if(lstPOI)
                        {
                            lstPOI.push(this.poi);
                        }
                        else
                        {
                            lstPOI = [];
                            lstPOI.push(this.poi);
                        }
                        
                    }
                    localStorage.setItem(CommonUtil.CONST_STORAGE_POI_LIST,JSON.stringify(lstPOI));
					this.$refs.sync.syncTwoWay();
                    this.$router.push('/places');
                },
                /** new POI pointOfInterestId */
                getNewPoiId(lstPOI)
                {
                    let newId = 0;
                    let poiIds=[];
                    
                    
                    if(lstPOI)
                    {
                        $.each(lstPOI, function(index, poi){
                            if(poi.pointOfInterestId < 0)
                            {
                            poiIds.push(Math.abs(poi.pointOfInterestId));
                            }
                        });
                        if(poiIds.length === 0)
                        {
                        newId = CommonUtil.CONST_POI_COUNT_START_ID;
                        }
                        else
                        {
                        let largestValue = Math.max.apply(null, poiIds);
                        newId = -Math.abs(largestValue + 1);
                        }
                    }
                    else
                    {
                        newId = CommonUtil.CONST_POI_COUNT_START_ID;
                    }

                    return newId;
                },




            myImage()
            {
               var fill = new Fill({
                color: 'white'
	            });
	
	            return new CircleStyle({
	                    radius: 15,
	                    fill: fill,
	                    stroke: new Stroke({color: '#3d8052', width: 15}),
	                    });
            },
            myVectorGeoSource(geoInfo){
                if(geoInfo)
                {
                    return new VectorSource({
                        features : new GeoJSON({dataProjection:"EPSG:4326", 
                        featureProjection:"EPSG:3857"}).readFeatures(geoInfo),
                    })
                }
            },
            myVectorGeoLayer(vectorSource,image){
                    return new VectorLayer({
                        source  :   vectorSource,
                        style   :   new Style({
                                            image: image,
                                        }),
                    })
            },

            myView(longitude,latitude,mapZoom){
                return new View ({
                                    center:fromLonLat([longitude,latitude]),
                                    zoom : mapZoom
                                })
            },  
            myOverLayCoord(longitude,latitude)
            {
                let coordinate = [longitude,latitude];
                return this.myOverLay(coordinate);
            },            
            myOverLay(coordinates){
                return new Overlay({
                                position :  fromLonLat(coordinates) ,
                                positioning: 'bottom-center',
                                element: document.getElementById('poiMarker'),
                                stopEvent: false                                
                            });
            },                      
            myInteractions(mapInteractions)
            {
                return (mapInteractions) ? [] : '';
            },
            
            /** My current location */
            myposition()
            {
                let options = { enableHighAccuracy: true };
                navigator.geolocation.getCurrentPosition(this.geolocationSuccess, this.geolocationError, options);
                //navigator.geolocation.getCurrentPosition(this.geolocationSuccess, this.geolocationError, this.geolocationOptions);

                
            },

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

            geolocationSuccess(pos) {
                      let This = this;
                    This.poi.latitude = pos.coords.latitude;
                    This.poi.longitude = pos.coords.longitude;
                    let coord = [pos.coords.longitude,pos.coords.latitude];

					// This is the marker icon for the location of the POI
                    let vectorLayer     =       new VectorLayer({
                                                        source  : new VectorSource ({
                                                                features    :   [
                                                                    new Feature({
                                                                        geometry : new Point(fromLonLat(coord))
                                                                    })
                                                                ],
                                                        }),
                                                        style   : new Style({
                                                                image : This.myImage()
                                                        })
                                                });
                        let     geoJSON         =   new GeoJSON();
                        let     resultGeoJSON   =   geoJSON.writeFeatures(vectorLayer.getSource().getFeatures(),{
                                            dataProjection: 'EPSG:4326',
                                            featureProjection: 'EPSG:3857' 
                                        });
						this.poi.geoJSON        =   resultGeoJSON;                                                

                        if(This.map)
                        {
                            let mapLayers       =       This.map.getLayers();
                            mapLayers.forEach(function(layer){
                                let source  =   layer.get('source');
                                source.clear();
                            })
                        This.map.addLayer(vectorLayer); 
                        This.map.getView().setCenter(fromLonLat(coord));
                        This.map.getView().setZoom(CommonUtil.CONST_GPS_OBSERVATION_ZOOM);
                    }
            },

            mapInit()
            {
                let This                =   this;
                let urlMap              =   CommonUtil.CONST_GPS_URL_NORWAY_MAP;
                let latitude            =   this.poi.latitude;
                let longitude           =   this.poi.longitude;  
                let mapZoom             =   this.mapZoom;              

                let geoInfo             =   '';
                if(this.poi && this.poi.geoJSON)
                {
                    geoInfo = JSON.parse(this.poi.geoJSON);
                }
                else
                {
                    let image = this.myImage();
                    latitude = CommonUtil.CONST_GPS_DEFAULT_LATITUDE_02_NORWAY;
                    longitude = CommonUtil.CONST_GPS_DEFAULT_LONGITUDE_02_NORWAY;
                    mapZoom   = CommonUtil.CONST_GPS_DEFAULT_ZOOM;

                    let coord = [CommonUtil.CONST_GPS_DEFAULT_LONGITUDE_02_NORWAY,CommonUtil.CONST_GPS_DEFAULT_LATITUDE_02_NORWAY];
                    let   transFormCord =       transform(coord, 'EPSG:3857','EPSG:4326');
                    let iconFeature = new Feature({
                        geometry: new Point(fromLonLat(transFormCord)) 
                    }); 

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

                    let     geoGSON         =   new GeoJSON();
                    let     resultGeoGSON   =   JSON.parse(geoGSON.writeFeatures(vectorLayer.getSource().getFeatures()));
                            //this.poi.geoJSON        =   JSON.stringify(resultGeoGSON);
                            geoInfo = resultGeoGSON;

                }

				// Set default POI type to field
				if(! this.poi.pointOfInterestTypeId)
				{
					this.poi.pointOfInterestTypeId = CommonUtil.CONST_POI_TYPE_DEFAULT;
				}

                    fetch(urlMap)
                    .then(function (response) {
                        return response.text();
                    })
                    .then(function (text) {
                        let parser  =   new WMTSCapabilities();
                        var result = parser.read(text);
                        var options = optionsFromCapabilities(result, {
                                            layer: 'topo4',
                                            matrixSet: 'EPSG:3857',
                                        });
                    
                         This.map =   new Map({
                                            layers: [
                                                        new TileLayer({
                                                            opacity: 1,
                                                            source: new WMTS(options),
                                                        }) ,                            
                                                        new VectorLayer({
                                                           source  :      new VectorSource({
                                                               features : new GeoJSON({
                                                                   dataProjection:"EPSG:4326", 
                                                                   featureProjection:"EPSG:3857"
                                                               }).readFeatures(geoInfo),
                                                           }),
                                                           style   :       new Style({
                                                              image: This.myImage(),
                                                           }),                                                
                                                       }),

                                                ],
                                            controls    :   [],
                                            target      :   'map-poi',
                                            view        :   new View({
                                                                    center  : fromLonLat([longitude,latitude]),
                                                                    zoom    : mapZoom,
                                                            }),
                                    });

                        /** Remove map pointer for first time newly poi  */
                        if(!This.poi.longitude)
                        {

                            let mapLayers       =       This.map.getLayers();
                            mapLayers.forEach(function(layer){
                                let source  =   layer.get('source');
                                source.clear();
                            })
                        }

                                    This.map.on(['singleclick'],function(event){
										if(!This.userCanEditPOI)
										{
											return;
										}
                                        let   transFormCord =       transform(event.coordinate, 'EPSG:3857','EPSG:4326');
                                              This.poi.longitude    =   transFormCord[0];
                                              This.poi.latitude     =   transFormCord[1];

                                                                    This.map.getView().setCenter(fromLonLat(transFormCord));
                                    
                                        let mapLayers       =       This.map.getLayers();
                                            mapLayers.forEach(function(layer){
                                                let source  =   layer.get('source');
                                                source.clear();
                                            })

                                        let vectorLayer     =       new VectorLayer({
                                                                            source  : new VectorSource ({
                                                                                            features    :   [
                                                                                                                new Feature({
                                                                                                                    geometry : new Point(fromLonLat(transFormCord))
                                                                                                                })
                                                                                                            ],
                                                                                    }),
                                                                            style   : new Style({
                                                                                                image : This.myImage()
                                                                                        })
                                                                    });

                                        This.map.addLayer(vectorLayer);

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




                    });

            },
            trimString(param)
            {
                return param.replace(/\s*/g,"")
            }


    },
    filters: {
    
        trim: function(string) {
            return string.trim()
            }
    
    },
    mounted() {
        var appDiv                      =   document.getElementById("app");
        var navDiv                      =   document.getElementById("vipsobsappmenu");
        var mapDiv                      =   document.getElementById("map-poi");
            appDiv.style.marginTop      =   "0";
            appDiv.style.paddingRight   =   "0";
            appDiv.style.paddingLeft    =   "0"; 
            mapDiv.style.height         =   (screen.height - navDiv.offsetHeight) + "px"; 

            this.mapZoom                =   CommonUtil.CONST_GPS_OBSERVATION_ZOOM;
            this.poiTypes               =   CommonUtil.CONST_POI_TYPES;
			//console.info(this.poiTypes);

        if(this.$route.params.pointOfInterestId)
        {
            this.getPointOfInterest(this.$route.params.pointOfInterestId);
        }
        this.mapInit();
        
        
    },
	 beforeDestroy() {
        // This resets the container layout when leaving the router page
 		var appDiv = document.getElementById("app");
		appDiv.style.marginTop="15px";
		appDiv.style.paddingRight="15px";
		appDiv.style.paddingLeft="15px"; 
    },    
}
</script>

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

    #btnBack{
        position: fixed;
        z-index: 1000;
    }
    #map-mylocation {
        position: fixed;    
        right: 0;
        z-index: 2000;
    }    
    #divPoiData {
        position: fixed;
        z-index: 1100;
        bottom: 0;
    }
</style>