var places = {},
    common = require('./../../utils/common.js'),
	logger = require('../../../logger'),
    semusiConfig = require('./../../config'),
    _ = require('underscore');
    client = require('node-rest-client').Client,
    foursquare = require('node-foursquare-venues')('I05ZLFERBGLKOQXTKL2KF1DKDNXWWQ1DZPEIGJUGTWSRTDC2', 'JORSGTLGVT3SGHNUKOEHP3MJPWKT0YQ4Q4YQHUCVPKOCSPTS');
(function (places) {

	places.getPlaces = function(params){
		if(params.qstring.radius==undefined){
			
		}
		//Check if lat/lng is provided then get places from lat/lng. Other wise check if wifi ids are given then get places from wifi ids.
		if(params.qstring.lat && params.qstring.lng && params.qstring.place){
			params.qstring.radius = semusiConfig.maxLatLngDistance;
			getPlacesFromLatLong(params);
		}
		else if(params.qstring.args && params.qstring.args.wifi && params.qstring.args.wifi.length>0 && params.qstring.place){
			params.qstring.radius = semusiConfig.maxWifiDistance;
			getPlacesFromWifiIds(params);
		}
		else{
			common.returnMessage(params,500,"Invalid parameters.");
		}	
		
	};

	//This method processes places from lat/lng
	function getPlacesFromLatLong(params){
		var lat = parseFloat(params.qstring.lat);
		var lng = parseFloat(params.qstring.lng);
		var place = params.qstring.place;
		common.db.command({
		    geoNear: "places",
		    near: { type: "Point", coordinates: [ lat,lng ] },
		    spherical: true,
		    query: { place: new RegExp(place, 'i')},
		    maxDistance:parseInt(params.qstring.radius),
		    limit:1
		},function(err,result) {
			logger.info(`result.results => ${result.results}`);	
			if(err){
				logger.error(`error => ${err}`);
				common.returnMessage(params,500,"Error while fetching data.");
				return true;
			}
			//if there is no data in mongo for the given coordinates, then hit foursquare. 
	   		if(result.results!==undefined && result.results.length==0){
	   			processFourSquareResults(params);
	   			//processgoogleAPIResults(params);
	   		}
	   		else{	   			   			
   				common.returnOutput(params,formatMongoData(result.results));
   			}	   			   		
	   	});	
	};

	//This function gets places from wifi ids.
	function getPlacesFromWifiIds(params){
		common.db.collection('places').find({ ssid: { $in: [ params.qstring.args.wifi ] } ,place: new RegExp(params.qstring.place, 'i')}).toArray(function(err,result){
			logger.info(`result => ${result}`);
			if(result && result.length>0){
				var data = checkPlaceInMongoDataForSSID(result,params.qstring.place);
				common.returnOutput(params,data);
			}
			else{
				
				processGeoLocationResults(params);
			}

		});
	};

	//This function will call foursquare api to get places for the given lat/long within a given radius.
	function processFourSquareResults(params){
		var lat = parseFloat(params.qstring.lat);
		var lng = parseFloat(params.qstring.lng);
		var radius = parseInt(params.qstring.radius);
		var place = params.qstring.place.toLowerCase();
		foursquare.venues.search({ll:lat+ ","+lng, radius:radius}, function(err, resp){
			//Return the first venue, and save rest of the venues for future reference.
			if(resp.response.venues && resp.response.venues.length>0){
				var data = checkPlaceInFoursquareOutput(resp.response.venues,place,radius);
				common.returnOutput(params,data);
				savePlacesFromFousquareAPI(resp.response.venues,params);	
			}
			else{
				processGoogleAPIResults(params);
			}
			
		});
	};


	//This function processes wifiids using geolocation API to get lat/lng and then inturn invokes foursquare to get places from retrieved lat long. 
	function processGeoLocationResults(params){
		var proxy = new client();
		var url = "https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyAzhsryLUZkk4CBlIXmZc9pyS3KBDuRURM";
		var args = {
			data: { "wifiAccessPoints": constructWifiDataObject(params.qstring.args.wifi) },
			headers:{"Content-Type": "application/json"} 
		};
		proxy.post(url, args, function(data,response) {
		    // parsed response body as js object 
		    if(data){
				logger.info(`data => ${data}`);
			    try{
			    	var loc = JSON.parse(data.toString());	
			    	if(loc.location){
			    		params.qstring.lat = loc.location.lat;
			    		params.qstring.lng = loc.location.lng;
			    		params.savewifi = true;
			    		processFourSquareResults(params);
			    	}
			    	else{
			    		common.returnOutput(params,[]);
			    	}
			    }
			    catch(e){
			    	common.returnOutput(params,[]);
			    }
			    
			}
			else{
				common.returnOutput(params,[]);
			}
		     
		    
		});
	};


	//This function will process google api results retrieved based on given lat/long.
	function processGoogleAPIResults(params){
		var lat = parseFloat(params.qstring.lat);
		var lng = parseFloat(params.qstring.lng);
		var radius = parseInt(params.qstring.radius);
		var place = params.qstring.place.toLowerCase();
		var proxy = new client();
		var key = semusiConfig.googleApiKey;
		var url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?";
		url+= "location="+lat+","+lng+"&radius="+ radius +"&sensor=false&key="+key;
		var args = {};
			
		proxy.get(url, args, function(data,response) {
		    // parsed response body as js object 
		    if(data){
		    	var resp = JSON.parse(data.toString());	
		    	var output = checkPlaceInGoogleAPIOutput(resp.results,place);
				common.returnOutput(params,output);
				savePlacesFromGoogleAPI(resp.results,params);	
		    }
		});    
	}
	//This function constructs data object in a format as required geolocation api.
	function constructWifiDataObject(data){
		var wifidata=[];
		data.forEach(function(item){
			var obj = {
				"macAddress":item
			}
			wifidata.push(obj);
		});

		return wifidata;
	}
	//This function will save the retrieved places to mongo collection.
	function savePlacesFromFousquareAPI(places,params){
		places.forEach(function(place) {			
			if(place.location && place.location.lat && place.location.lng){				
				common.db.command({
				     geoNear: "places",
				     near: { type: "Point", coordinates: [ place.location.lat, place.location.lng ] },
				     spherical: true,
				     maxDistance:parseInt(params.qstring.radius),
				   },function(err,result) {
				   		if(result.results && result.results.length==0){				   			
				   			var name = (place.name !== undefined) ? place.name.toLowerCase():"";
				   			var address = (place.location.address !== undefined) ? place.location.address.toLowerCase():"";
				   			var categories = [];
				   			place.categories.forEach(function(cat){
				   				categories.push(cat.name.toLowerCase());
				   			});
				   			//Save only those places which we use for campaign targetting.
				   			var savePlace = false;
				   			var keyswords ="";
				   			semusiConfig.places.forEach(function(cp){
				   				
					   			if(wordInString(name,cp.place) || wordInString(address,cp.place) || wordInString(categories.toString(),cp.place)){
						   			savePlace = true;
						   			keyswords+=cp.group +",";						   			
					   			}
					   			
				   			});
				   			var newPlace={
				   				name:name,	
				   				category : categories,
				   				place:keyswords,
				   				loc:{
				   					type:"Point",
				   					coordinates:[place.location.lat, place.location.lng]
				   				}
				   			};
				   			
				   			if(params.savewifi){
				   				newPlace.ssid = params.qstring.args.wifi;
				   			}
				   			if(savePlace && place.location.distance<=parseInt(params.qstring.radius)){
				   				newPlace['createdAt'] = common.getCurrentEpochTime();
				   				common.db.collection('places').insert(newPlace,function (err,res) {});	
				   			}
				   		}				   		
				});
			}
		});
	}

	//This function will save the retrieved places to mongo collection.
	function savePlacesFromGoogleAPI(places,params){
		places.forEach(function(place) {			
			if(place.geometry && place.geometry.location && place.geometry.location.lat && place.geometry.location.lng){				
				common.db.command({
				     geoNear: "places",
				     near: { type: "Point", coordinates: [ place.geometry.location.lat, place.geometry.location.lng ] },
				     spherical: true,
				     maxDistance:parseInt(params.qstring.radius),
				   },function(err,result) {
				   		if(result.results && result.results.length==0){				   			
				   			var name = (place.name !== undefined) ? place.name.toLowerCase():"";
				   			var address = (place.vicinity !== undefined) ? place.vicinity.toLowerCase():"";
				   			var categories = (place.type !==undefined)? place.type : [];				   			
				   			//Save only those places which we use for campaign targetting.
				   			var savePlace = false;
				   			var keyswords ="";
				   			semusiConfig.places.forEach(function(cp){
				   				
					   			if(wordInString(name,cp.place) || wordInString(address,cp.place) || wordInString(categories.toString().toLowerCase(),cp.place)){
						   			savePlace = true;
						   			keyswords+=cp.place +",";						   			
					   			}
					   			
				   			});
				   			var newPlace={
				   				name:name,	
				   				category : categories,
				   				place:keyswords,
				   				loc:{
				   					type:"Point",
				   					coordinates:[place.geometry.location.lat, place.geometry.location.lng]
				   				}
				   			};
				   			
				   			if(params.savewifi){
				   				newPlace.ssid = params.qstring.args.wifi;
				   			}
				   			if(savePlace && place.location.distance<=parseInt(params.qstring.radius)){
				   				newPlace['createdAt'] = common.getCurrentEpochTime();
				   				common.db.collection('places').insert(newPlace,function (err,res) {});	
				   			}
				   		}				   		
				});
			}
		});
	}


	//This function checks if the requested places exists in data fetched from foursquare API.
	function checkPlaceInFoursquareOutput(data,place,radius){
		 
		var output = [];
		var placeParts = getRelatedPlaces(place);		
		for(var i=0; i<data.length;i++){
			var item = data[i];
			if(item.location.distance<=radius){
				var name = (item.name !== undefined) ? item.name.toLowerCase():"";
	   			var address = (item.location.address !== undefined) ? item.location.address.toLowerCase():"";
				var category = [];
				item.categories.forEach(function (cat) {
					category.push(cat.name.toLowerCase());
				});
				placeParts.forEach(function(p){
					if(wordInString(name,p) || wordInString(category.toString(),p) || wordInString(address,p)){
						output.push({"place":place,"dis":item.location.distance});	
					}				
				});
				if(output.length>0){
					break;
				}
			}
			
		}
		 
		if(output.length==0){
			 
		}
		return output;
	}

	//This function checks if the requested places exists in data fetched from google API.
	function checkPlaceInGoogleAPIOutput(data,place){
		 
		var output = [];
		var placeParts = getRelatedPlaces(place);		
		for(var i=0; i<data.length;i++){
			var item = data[i];			
			var name = (item.name !== undefined) ? item.name.toLowerCase():"";
   			var address = (item.vicinity !== undefined) ? item.vicinity.toLowerCase():"";
			var category = (item.type !==undefined)? item.type : [];			
			placeParts.forEach(function(p){
				if(wordInString(name,p) || wordInString(category.toString().toLowerCase(),p) || wordInString(address,p)){
					output.push({"place":place,"dis":item.location.distance});	
				}				
			});
			if(output.length>0){
				break;
			}
		
			
		}
		 
		if(output.length==0){
			 
		}
		return output;
	}

	function formatMongoData(data){		
		logger.info(`data => ${data}`);
		 
		var output = [];
		data.forEach(function(item){							
			output.push({"place":item.obj.place,"dis":item.dis});		
		});			
					
		return output;
	}

	function checkPlaceInMongoDataForSSID(data,place){
		 
		var output = [];
		var placeParts = getRelatedPlaces(place);
		logger.info(`placeparts=> ${placeParts}`);
		for(var i=0,num=data.length;i<num;i++){
			var item = data[i];
			placeParts.forEach(function(p){
				if(wordInString(item.place,p)){
					output.push({"place":item.place,"dis":0});							
				}									
			});
			if(output.length>0){
				break;
			}			
		}
		 
		if(output.length==0){
			 
		}
		return output;
	}

	function wordInString(s, word){
		return new RegExp( '\\b' + word + '\\b', 'i').test(s);
	}
	
	function getRelatedPlaces(place){
		var values=[];
		for (var i = 0,num = semusiConfig.places.length; i < num; i++) {
			if(semusiConfig.places[i].place==place){
				values = semusiConfig.places[i].group.split(',');
				break;
			}
		};

		return values;
	}
}(places));

module.exports = places;    