var loader = new PIXI.Loader();
var colors = ['66FF00','FF5555','FFE419','2A7FFF','BC5FD3','C8AB37','ECECEC','FF6600'];
for (var i in colors){
	loader.add('marker'+colors[i]+'', 'src/img/plane-'+colors[i]+'.png');
}

//global variable
var nbPlane = 0

loader.add('shadow', 'src/img/shadow.png');
loader.load(function(loader, resources) {
    
    var pixiContainer = new PIXI.Container();
    	
	var map = L.map('map',{ 
		zoomControl: false,
		minZoom:2,
        maxZoom: 16,
		maxBounds: [
			[-Infinity, -360],
			[Infinity, 360]
        ],
		//worldCopyJump: true,
		attributionControl: false
	})
	
	//zoom controls	
	L.control.zoom({position: 'bottomright'}).addTo(map);
	//Locate user
	L.control.locate({position: 'bottomright'}).addTo(map);
	//fullscreen
	map.addControl(new L.Control.Fullscreen({position: 'bottomright'}));
	
	// Licence Icon
	L.Control.Watermark = L.Control.extend({
		onAdd: function(map) {
			var img = L.DomUtil.create('img');

			img.src = 'src/img/licence.svg';
			img.style.width = '100px';

			return img;
		}
	});
	L.control.watermark = function(opts) {
		return new L.Control.Watermark(opts);
	}
	L.control.watermark({ position: 'bottomleft' }).addTo(map);
	//scale
	L.control.scale().addTo(map);
	
	//disabling send plane button if alreada 100 planes sent the current day
	
	
	$.post("avionJournalier.php", function(result) {
		result = result.replace(/'/g, '"');
		result = $.parseJSON(result)
		nbPlane = Number(result.nAvion)
		$("#buttonNewPlane").val("Lancer un avion-poème "+Number(result.nAvion)+"/100")
		if (nbPlane > 99){
			$("#buttonNewPlane").prop("disabled",true);
		}
		else{
			
		}
		translateUI(lang)
	})
	
	//background
	L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
		attribution: '',
		//minZoom:8,
		maxZoom: 16,
	}).addTo(map);

    //adding terminator
	var terminator = L.terminator()
	.addTo(map);
	 setInterval(function() {
		  terminator.setTime();
	 }, 1000);
	

	//center map on sun by default
	function centerOnSun(){
		var equator = turf.lineString([[-1000, 0], [1000, 0]])
		var intersects = turf.lineIntersect(equator, terminator.toGeoJSON());
		//console.log(intersects)
		var lonCenter = ((intersects.features[1].geometry.coordinates[0])+(intersects.features[2].geometry.coordinates[0]))/2
		//console.log(lonCenter)
		return lonCenter
	}
	map.setView([30,0], 2);
	
	
	//could layer from GBIS NASA  - always 1 day of delay
	var twoDaysAgo = moment(new Date()).subtract(2, "days").format('YYYY-MM-DD')
	L.tileLayer('https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_SNPP_CorrectedReflectance_TrueColor/default/'+twoDaysAgo+'/GoogleMapsCompatible_Level9/{z}/{y}/{x}.jpg', {
		attribution: '',
		maxZoom: 8,
		opacity:0.4
	})
	.addTo(map);
	
	
	//Bluring the terminator | Source: https://stackoverflow.com/questions/28235792/leaflet-polygon-with-fuzzy-outline
	var svg = map.getPanes().overlayPane.firstChild,
	svgFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter'),
    svgBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
	svgFilter.setAttribute('id', 'blur');
	svgFilter.setAttribute('x', '-100%');
	svgFilter.setAttribute('y', '-100%');
	svgFilter.setAttribute('width', '500%');
	svgFilter.setAttribute('height', '500%');
	svgBlur.setAttribute('stdDeviation', 15);
	svgFilter.appendChild(svgBlur);
	svg.appendChild(svgFilter);
	terminator._path.setAttribute('filter', 'url(#blur)'); 
	
	//geojson for arclines 
	//travel
	var arcTravelStyle = {   
		"color": "#00ff00",
		"weight": 2.5,
		"dashArray": "10 5",
		"opacity": 0.65
	};
	var arcTravel = L.geoJSON([],{style: arcTravelStyle}).addTo(map);
	//travelled
	var arcTravelledStyle = {   
		"color": "#00ff00",
		"weight": 2.5,
		"opacity": 0.65
	};
	var arcTravelled = L.geoJSON([],{style: arcTravelledStyle}).addTo(map);

	var pulsatingMarker = L.layerGroup([]).addTo(map) 	
	var originMarker = L.layerGroup([]).addTo(map) 	
    
    var firstDraw = true;
    var prevZoom;
	
    var pixiOverlay = L.pixiOverlay(function(utils, event) {
        var zoom = utils.getMap().getZoom();
        var container = utils.getContainer();
        var renderer = utils.getRenderer();
        var project = utils.latLngToLayerPoint;
        var scale = utils.getScale();
		
        if (firstDraw) {
			
			//get planes
			$.post( "getCurrentPlanes.php", function(result) {
			 // console.log(result)
			  var planes = $.parseJSON(result)
			  console.log(planes)
			  function formatResults(data){
				  data.deliveryTime = Number(data.deliveryTime)*1000
				  data.startTime = Number(data.startTime)*1000
				  return data
			  }
			  
			  function displayPlane(data){
					var line = turf.greatCircle(turf.point([Number(data.startLon),Number(data.startLat)]), turf.point([Number(data.destLon),Number(data.destLat)]),{offset:20})
					var lineDistance = turf.length(line);
					var dateStart = moment(data.startTime)
					var dateEnd = moment(data.deliveryTime)
					var dateNow = moment(new Date())
					var totalSeconds = dateEnd.diff(dateStart,'seconds');
					var travelledSeconds = dateNow.diff(dateStart,'seconds')
					var travelRatio = travelledSeconds/totalSeconds
					var travelledDistance = lineDistance*travelRatio  // getting the travelled distance
					var segment;
					if(line.geometry.type == "MultiLineString"){ // if the arc is cutting the dateline, well it's a mess.
						var l1 = turf.lineString(line.geometry.coordinates[0]) // creating a line from first segment
						var l2 = turf.lineString(line.geometry.coordinates[1]) // creating a line from second segment
						var l1Length = turf.length(l1) // calculating length of first segment
						if (travelledDistance < l1Length){ // if the travelled distance is inferior to segment 1 line, the point is somewhere in it
							segment = l1
							data.position = 1
						}
						else{
							segment = l2  // otherwise on segment 2
							data.position = 2
							travelledDistance = Number(travelledDistance)-Number(l1Length) // we remove the travel distance done in s1
						}
					}
					else{
						segment = line
						data.position = 0						
					}
					var currentPosition = turf.along(segment, travelledDistance,{units: 'kilometers'})
					if(currentPosition.geometry.coordinates[0] < -180){currentPosition.geometry.coordinates[0] = currentPosition.geometry.coordinates[0]+360}
					if(currentPosition.geometry.coordinates[0] > 180){currentPosition.geometry.coordinates[0] = currentPosition.geometry.coordinates[0]-Number(360)}
				    //calculating bearing based on two points, one just before and one just after
					var positionBefore = turf.along(segment, (travelledDistance)-0.00001,{units: 'kilometers'})
					var positionAfter = turf.along(segment, (travelledDistance)+0.00001,{units: 'kilometers'})
					var rotation = turf.bearing(
						positionBefore,
						positionAfter
					);
					
					//plane
					var iconColor = 'marker'+data.color
					var markerTexture = resources[iconColor].texture;
					var marker = new PIXI.Sprite(markerTexture);
					marker.anchor.set(0.5, 0.5);
					var markerCoords = project([currentPosition.geometry.coordinates[1],currentPosition.geometry.coordinates[0]]);
					marker.x = markerCoords.x;
					marker.y = markerCoords.y;
					marker.angle = rotation;
					marker.scale.set(5);
					marker.interactive = true;
					marker.cursor = 'pointer'
					marker.data  = data
					marker.data.line = line
					marker.data.currentPosition = currentPosition
					
					//shadow
					var shadowTexture = resources.shadow.texture;
					var shadow = new PIXI.Sprite(shadowTexture);
					shadow.anchor.set(0.5, 0.5);
					shadow.x = markerCoords.x;
					shadow.y = markerCoords.y + 0.5;
					shadow.angle = rotation;
					shadow.scale.set(0.00025);
					shadow.alpha = 0.3
					shadow.visible = false
								
					//popup
					marker.popup = L.popup({className: 'pixi-popup'})
					
					pixiContainer.addChild(shadow);
					pixiContainer.addChild(marker);
					
					renderer.render(container)	
					
					//adapting scale based on zoom level. Max zoom = writting visible
					map.on('zoomend', function() {
						marker.scale.set((1/(utils.getScale(map.getZoom())*20))+(Math.pow(map.getZoom(),2)/100*2*(1/(utils.getScale(map.getZoom())*20))))
						if(map.getZoom() == 16){
							shadow.visible = true
						}
						else{
							shadow.visible = false
						}
					});
					
					
					
					//animating moving plane
					setInterval(function() {
					  animate();
					}, 1000)
					
					function animate() {
				      if (map.getZoom()	> 12){ // we animate only starting zoom 12
						  var bounds = map.getBounds()
						  var bbox = [bounds._southWest.lng, bounds._southWest.lat, bounds._northEast.lng, bounds._northEast.lat];  
						  var extentPoly = turf.bboxPolygon(bbox);
						  var planeInExtent = turf.booleanWithin(marker.data.currentPosition, extentPoly);
							  if(planeInExtent == true){ // we animate only the planes in map extent 
							  var dateNow = moment(new Date())
							  var totalSeconds = dateEnd.diff(dateStart,'seconds');
							  var travelledSeconds = dateNow.diff(dateStart,'seconds')
							  var travelRatio = travelledSeconds/totalSeconds
							  var lineDistance = turf.length(line);
							  var segment;
							  var travelledDistance = lineDistance*travelRatio  // getting the travelled distance
								if(line.geometry.type == "MultiLineString"){ // if the arc is cutting the dateline
									var l1 = turf.lineString(line.geometry.coordinates[0]) // creating a line from first segment
									var l2 = turf.lineString(line.geometry.coordinates[1]) // creating a line from second segment
									var l1Length = turf.length(l1) // calculating length of first segment
									if (travelledDistance < l1Length){ // if the travelled distance is inferior to segment 1 line, the point is somewhere in it
										segment = l1
										marker.data.position = 1  // we store it, usefull for popup event
									}
									else{
										segment = l2  // otherwise on segment 2
										marker.data.position = 2
										travelledDistance = Number(travelledDistance)-Number(l1Length) // we remove the travel distance done in s1
									}
								}
								else{
									segment = line	
								}
							  var currentPosition = turf.along(segment, travelledDistance,{units: 'kilometers'})
							  //troubleshooting extreme lons
							  if(currentPosition.geometry.coordinates[0] < -180){currentPosition.geometry.coordinates[0] = currentPosition.geometry.coordinates[0]+360}
							  if(currentPosition.geometry.coordinates[0] > 180){currentPosition.geometry.coordinates[0] = currentPosition.geometry.coordinates[0]-Number(360)}
							  marker.data.currentPosition = currentPosition
							  var markerCoords = project([currentPosition.geometry.coordinates[1],currentPosition.geometry.coordinates[0]]);
							  marker.x = markerCoords.x;
							  marker.y = markerCoords.y;
							  shadow.x = markerCoords.x;
							  shadow.y = markerCoords.y + 0.5;
							  renderer.render(container);
						  }
					   }
					}
					
					//if parameter in URL, zoom on it
					var queryString = window.location.search;
					queryString = queryString.split('=')[1]
					if(Number(queryString)==data.uid){
						/*
						Activate anim place reverse
						$("#back").attr("src","src/img/back-"+data.color+".jpg");
						html = data.message;
						var canvas1 = document.getElementById("blankCanvas1");
						rasterizeHTML.drawHTML(html, canvas1,{zoom:0.7}).then(function success(renderResult) {
							var canvas2 = document.getElementById("blankCanvas2");
							var ctx = canvas2.getContext("2d");
							ctx.fillStyle = "#" + data.color;
							ctx.fillRect(0,0,400,400);
							ctx.drawImage(canvas1, 0, 0,400,400)
							ctx.font = "9px Courier";
							$("#front").attr('src',document.getElementById("blankCanvas2").toDataURL())
							$("#canvas3d").css('display','block')
							animePlane();
						})
						*/
					}
					
				}
				for (var i in planes){
					displayPlane(formatResults(planes[i]),0)		
				}
			});
			
			function openPopup(target){
				//drawing arcs
					arcTravel.clearLayers()
					arcTravelled.clearLayers()
					arcTravelStyle.color = '#'+target.data.color
					arcTravelledStyle.color = '#'+target.data.color
					var travel = target.data.line
					var start = turf.point([Number(target.data.startLon),Number(target.data.startLat)])
					var current =  target.data.currentPosition
					var end = turf.point([Number(target.data.destLon),Number(target.data.destLat)])
					// for linestrings
					if(travel.geometry.type == "LineString"){ 
						var sliced1 = turf.lineSlice(start, current, travel);
						var sliced2 = turf.lineSlice(current, end, travel);
						arcTravelled.addData(sliced1);
						arcTravel.addData(sliced2);
					}
					// we create a copy of lines crossing the datetime
					function createCopy(c){
						for (var i in c.geometry.coordinates){
							if (c.geometry.coordinates[i][0] > 0){
								c.geometry.coordinates[i][0] = c.geometry.coordinates[i][0] - Number(360)
							}
							else{
								c.geometry.coordinates[i][0] = c.geometry.coordinates[i][0] + Number(360)
							}
						}

						return c
					}
					//for multilinetrings
					if(travel.geometry.type == "MultiLineString"){
						var l1 = turf.lineString(travel.geometry.coordinates[0]) // creating a line from first segment
						var l2 = turf.lineString(travel.geometry.coordinates[1]) // creating a line from second segment
						if(target.data.position == 1){
							var sliced1 = turf.lineSlice(start, current, l1);
							var sliced2 = turf.lineSlice(current, turf.point(l1.geometry.coordinates[l1.geometry.coordinates.length-1]), l1);
							arcTravelled.addData(sliced1);
							arcTravel.addData(sliced2);
							arcTravel.addData(l2);
							
						}
						else if(target.data.position == 2){
							var sliced1 = turf.lineSlice(turf.point(l2.geometry.coordinates[0]), current, l2);
							var sliced2 = turf.lineSlice(current, end, l2);
							arcTravelled.addData(l1);
							arcTravelled.addData(sliced1);
							arcTravel.addData(sliced2);	
						}
						var travelledGeoJSON = arcTravelled.toGeoJSON()
						for (var i in travelledGeoJSON.features){
							arcTravelled.addData(createCopy(travelledGeoJSON.features[i]))
						}
						var travelGeoJSON = arcTravel.toGeoJSON()
						for (var i in travelGeoJSON.features){
							arcTravel.addData(createCopy(travelGeoJSON.features[i]))
						}
						
					}
					
					
					//add pulsating marker on destination;
					pulsatingMarker.clearLayers()
					var pulseIcon = L.divIcon({
					  className: 'pulse-icon', //empty class to overwrite leaflet defaults
					  html: '<div class="pulse-icon-anim" style="border-color:#'+target.data.color+'"></div>',
					  iconSize: [22,22]
					});
					var endCoordo = [Number(target.data.destLat),Number(target.data.destLon)]
					pulsatingMarker.addLayer(new L.marker(endCoordo, {icon: pulseIcon}));
					if(travel.geometry.type == "MultiLineString"){ //if arc cross dateline, we multiply the marker
						pulsatingMarker.addLayer(new L.marker([endCoordo[0],endCoordo[1]-Number(360)], {icon: pulseIcon}));
						pulsatingMarker.addLayer(new L.marker([endCoordo[0],endCoordo[1]+Number(360)], {icon: pulseIcon}));
					}
					
					//adding static marker on origin
					originMarker.clearLayers()
					var startCoordo = [Number(target.data.startLat),Number(target.data.startLon)]
					originMarker.addLayer(new L.circleMarker(startCoordo, {radius: 6,opacity:0.7, weight:2,color:'#'+target.data.color}));
					if(travel.geometry.type == "MultiLineString"){ //if arc cross dateline, we multiply the marker
						originMarker.addLayer(new L.circleMarker([startCoordo[0],startCoordo[1]-Number(360)], {radius: 6,opacity:0.7,weight:2,color:'#'+target.data.color}));
						originMarker.addLayer(new L.circleMarker([startCoordo[0],startCoordo[1]+Number(360)], {radius: 6,opacity:0.7,color:'#'+target.data.color}));
					}
					
					
					
					//popup
					var momentLocale = lang;
					if (momentLocale == 'zh'){momentLocale = 'zh-cn'} //troubleshot for chinese
					moment.locale(momentLocale)
					
					target.popup.setLatLng([target.data.currentPosition.geometry.coordinates[1],target.data.currentPosition.geometry.coordinates[0]])
					//arabic popup
					if(lang=="ar"){
						target.popup.setContent('<table><tbody><tr><th style="text-align:center">'+target.data.startName+'</th><th>&nbsp;<i class="fas fa-plane"></i>&nbsp;</th><th style="text-align:center">'+target.data.destName+'</th></tr><tr><th style="text-align:center"><small>'+moment(target.data.startTime).fromNow()+'</small></th><th></th><th style="text-align:center"><small>'+moment(target.data.deliveryTime).fromNow()+'</small></th></tr></tbody></table>')
					}
					//other languages
					else{
						target.popup.setContent('<table><tbody><tr><th style="text-align:center">'+target.data.startName+'</th><th>&nbsp;<i class="fas fa-plane"></i>&nbsp;</th><th style="text-align:center">'+target.data.destName+'</th></tr><tr><th style="text-align:center"><small>'+moment(target.data.startTime).fromNow()+'</small></th><th></th><th style="text-align:center"><small>'+moment(target.data.deliveryTime).fromNow()+'</small></th></tr></tbody></table>')
					}
					target.popup.openOn(map);
					target.popup.on('remove', function() {
						arcTravel.clearLayers()
						arcTravelled.clearLayers()
						pulsatingMarker.clearLayers()
						originMarker.clearLayers()
					});
					target.popup.on('popupclose', function() {
						arcTravel.clearLayers()
						arcTravelled.clearLayers()
						pulsatingMarker.clearLayers()
						originMarker.clearLayers()
					});
			}
			//utils for popup
			utils.getMap().on('click', function(e) {
				var interaction = utils.getRenderer().plugins.interaction;
				var pointerEvent = e.originalEvent;
				var pixiPoint = new PIXI.Point();
				interaction.mapPositionToPoint(pixiPoint, pointerEvent.clientX, pointerEvent.clientY);
				var target = interaction.hitTest(pixiPoint, container);
				if (target && target.popup) {
					openPopup(target)
				}
			});
			utils.getMap().on('touchend', function(e) {
				var interaction = utils.getRenderer().plugins.interaction;
				var pointerEvent = e.originalEvent;
				var pixiPoint = new PIXI.Point();
				interaction.mapPositionToPoint(pixiPoint, pointerEvent.clientX, pointerEvent.clientY);
				var target = interaction.hitTest(pixiPoint, container);
				if (target && target.popup) {
					openPopup(target)
				}
			});
			
			
        }

        firstDraw = false;
        prevZoom = zoom;
        renderer.render(container);
    }, pixiContainer);
    pixiOverlay.addTo(map);
});





  
//hack to make white lines between lines disapear on non-retina screens (from: https://github.com/Leaflet/Leaflet/issues/3575 )
(function(){
    var originalInitTile = L.GridLayer.prototype._initTile
    L.GridLayer.include({
        _initTile: function (tile) {
            originalInitTile.call(this, tile);

            var tileSize = this.getTileSize();

            tile.style.width = tileSize.x + 1 + 'px';
            tile.style.height = tileSize.y + 1 + 'px';
        }
    });
})()
