/*
	This file is part of LocalBuzz.

    LocalBuzz is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar 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
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
* --------------------------------------------------------------------
* LocalBuzz Main App
* --------------------------------------------------------------------
*/
window.addEvent('domready', function() {
	var FILTER_COOKIE_ID = 'localbuzz.filter.cookie';
	
	var isAndroidDevice = navigator.userAgent.toLowerCase().search( "android") != -1;
	var isIPhone = navigator.userAgent.toLowerCase().search( "iphone") != -1;
	
	var currentLat = 0;
	var currentLon = 0;
	var currentPage = 1;
	var currentFilter = "";
	var currentFilterCookie = null;
	var currentRadius = "25km";
	var tweetsPerPage =  20;
	var lastTweedId = null;
	var maxTweetId = null;
	
	var progressIndicator = null;
	var progressIndicatorContainer = null;
	
	var buzzStreamContainer = $('localbuzz-stream');
	
	var moreButton = null;
	var filterForm = $('filter-form');
	
	var twitterSearchRequest = null;
	
	// Init Application
	if(geo_position_js.init()) {
		geo_position_js.getCurrentPosition(locationFoundHandler,locastionNotFoundHandler,{enableHighAccuracy:true});
		initApp();
	} else{
		showErrorMessage('<p>Sorry, Geolocation API is not available in your browser. I simply cannot figure out where you are...</p><p>&nbsp;</p><p>- Check the <a href="http://www.intuity.de/aktuelles/apps/localbuzz">system requirements</a> for LocalBuzz</p>');
	}
	
	// Main Initialization
	function initApp() {
		
		clearStream();
		buildProgressIndicator();
		showProgressIndicator('Tryin to get your location');
		
		twitterSearchRequest = new Request.JSONP({
			url: 'http://search.twitter.com/search.json',
			noCache: true,
			onComplete: function (result) {
				twitterSearchResultHandler(result);
			}
		});
		
		filterForm.addEvent( 'submit', function(e){
			e.stop();
			filterFormSubmitHandler();
		});
		
	}
	
	function filterFormSubmitHandler() {
		clearStream();
		
		currentFilter = $('q').get('value');
		
		if (currentFilter!="" && currentLat!=0 && currentLon!=0) {
			currentFilterCookie = Cookie.write(FILTER_COOKIE_ID, currentFilter);
		} else {
			Cookie.dispose(FILTER_COOKIE_ID);
		}
		invokeTwitterSearch();
	}
	
	
	function clearStream () {
		maxTweetId = null;
		lastTweedId = null;
		
		currentPage = 1;
		// save and remove more button
		if (moreButton!=null) {
			moreButton = moreButton.dispose();
		}
		
		buzzStreamContainer.empty();
	} 
	
	function locationFoundHandler(position) {
		var searchParams = null;
		currentLat = position.coords.latitude;
		currentLon = position.coords.longitude;
		
		currentFilterCookie = Cookie.read(FILTER_COOKIE_ID);
		if (currentFilterCookie!=null && currentFilterCookie!='') {
			$('q').set('value',currentFilterCookie);
			currentFilter = currentFilterCookie;
		}
		invokeTwitterSearch();
	}
	
	function locastionNotFoundHandler() {
		showErrorMessage("<p>Could not determine your location!</p><p>- If you're using a mobile phone, please enable your wifi location module.</p><p>- Or try again...</p>");
	}
	
	function invokeTwitterSearch(params) {
		
		showProgressIndicator("Checkin' your hood");
			
		var params = {geocode: currentLat +',' + currentLon + ","+ currentRadius, rpp:tweetsPerPage, page:currentPage}
		
		if (currentFilter!=null) {
			params.q = currentFilter;
		}
		if (maxTweetId!=null) {
			params.max_id = maxTweetId; 
		}
		
		var searchParams = {'data': params};
		
		twitterSearchRequest.send(searchParams);
		
	}
	
	function twitterSearchResultHandler(tweets) {
			if (maxTweetId == null) {
				maxTweetId = tweets.max_id;
			}
			
			hideProgressIndicator();
			
			if (lastTweedId==null) {
				buzzStreamContainer.empty();
			} 
			
			
			tweets.results.each(function(tweet) {
				lastTweedId = tweet.id;
				var creationDate = new Date(tweet.created_at);
				var newTweet = new Element('div',{
					'id': tweet.id,
					'html':  '<a href="'+ UrlHelper.getTwitterUrlForUser(tweet.from_user) +'"><img src="'+tweet.profile_image_url+'" class="author-image" /></a><p class="buzz-content">' + UrlHelper.linkify(tweet.text) + '</p> <p class="buzz-meta">said <a href="'+UrlHelper.getTwitterUrlForUser(tweet.from_user)+'">'+tweet.from_user+'</a> from '+ tweet.location +' '+creationDate.timeDiffInWords() +'</p>' 
				});
				newTweet.addClass('buzz-entry').injectInside(buzzStreamContainer);
				if (!isAndroidDevice) {
					//alert(navigator.userAgent.toLowerCase());
					newTweet.setStyle('opacity',0).tween('opacity',1);
				} 
			});
			
			if (tweets.next_page!=null) {
				showMoreButton();
				currentPage++;
			}
	}
	
	function showMoreButton () {
		if (moreButton!= null) {
			moreButton.injectInside(buzzStreamContainer);
			return;
		} else {
			moreButton = new Element('div',{
				'id': 'more-button',
				'html':  '<a href="#more">More buzz ...</a>',
				'events': {
        			'click': function(e){
        				e.stop();
        				moreButtonClickedHandler();
            		}
            	}
    		}).addClass('buzz-entry').addClass('more-button').injectInside(buzzStreamContainer);
		}
		
	} 
	
	function moreButtonClickedHandler () {
		moreButton = moreButton.dispose();
		invokeTwitterSearch();
		//invokeTwitterSearch({geocode: currentLat +',' + currentLon + ","+ currentRadius, rpp:tweetsPerPage , page:currentPage, max_id: maxTweetId});
	} 
	
	
	function buildProgressIndicator() {
		if (progressIndicatorContainer == null) {
			progressIndicatorContainer = new Element('div',{
					'id': "progress-indicator",
					'html':  '' 
			});
			progressIndicatorContainer.addClass('buzz-entry').addClass('progress-indicator').injectInside(buzzStreamContainer);
			progressIndicator = new Dotter(progressIndicatorContainer, {
				dot:' &bull; ', 
				delay: 300, 
				property: 'html', 
				numDots:6
			}); 
		}
	}
	
	function showProgressIndicator(message) {	
		if(progressIndicator != null) {
			progressIndicatorContainer.injectInside(buzzStreamContainer);
			if (message!=null) {
				progressIndicator.setOptions({'message': message});
			}
			progressIndicator.start();
		}
	}
	
	function hideProgressIndicator() {	
		if(progressIndicator != null) {
			progressIndicator.stop();
			progressIndicatorContainer = progressIndicatorContainer.dispose();
		}
	}
	
	function showErrorMessage (message) {
		buzzStreamContainer.set('html', '<div class="buzz-entry error-message">'+message+'</div>');
	} 
	
});


/*
* --------------------------------------------------------------------
* Helpers
* --------------------------------------------------------------------
*/
var UrlHelper = {

	getTwitterUrlForUser: function(userId) {
		return "http://www.twitter.com/"+ userId;
	},
   
   linkify: function(text) {
		// modified from TwitterGitter by David Walsh (davidwalsh.name)
		// courtesy of Jeremy Parrish (rrish.org)
		return text.replace(/(https?:\/\/[\w\-:;?&=+.%#\/]+)/gi, '<a href="$1">$1</a>')
				   .replace(/(^|\W)@(\w+)/g, '$1<a href="http://twitter.com/$2">@$2</a>')
				   .replace(/(^|\W)#(\w+)/g, '$1#<a href="http://search.twitter.com/search?q=%23$2">$2</a>');
  	
   }
}



/*
* --------------------------------------------------------------------
* Dotter Class by David Walsh (http://davidwalsh.name/mootools-dotter)
* --------------------------------------------------------------------
*/
var Dotter = new Class({
	
	/* implements */
	Implements: [Options,Events],

	/* options */
	options: {
		delay: 1000,
		dot: '.',
		message: 'Loading',
		numDots: 3,
		property: 'text',
		reset: false/*,
		onDot,
		onStart,
		onStop
		*/
	},
	
	/* initialization */
	initialize: function(container,options) {
		/* set options */
		this.setOptions(options);
		this.container = $(container);
		this.dots = 0;
		this.running = false;
	},
	
	/* adds dot */
	dot: function() {
		if(this.running) {
			var text = this.container.get(this.options.property);
			this.dots++;
			this.container.set(this.options.property,(this.dots % this.options.numDots != 0 ? text : this.options.message) + '' + this.options.dot);
		}
		return this;
	},
	
	/* loads or resets the dotter */
	load: function() {
		this.loaded = true;
		this.dots = 0;
		this.dotter = function(){ this.dot(); this.fireEvent('dot'); }.bind(this);
		this.periodical = this.dotter.periodical(this.options.delay);
		this.container.set(this.options.property,this.options.message + '' + this.options.dot);
		return this;
	},
	
	/* start the dotter */
	start: function() {
		if(!this.loaded || this.options.reset) this.load();
		this.running = true;
		this.fireEvent('start');
		return this;
	},
	
	/* stop the dotter */
	stop: function() {
		this.running = this.loaded = false;
		$clear(this.periodical);
		this.fireEvent('stop');
		return this;
	}
});





/*
* -------------------------------------------------------------------------------------
* geo-location-javascript Framework (http://code.google.com/p/geo-location-javascript/)
* -------------------------------------------------------------------------------------
*/
var bb_successCallback;
var bb_errorCallback;
function handleBlackBerryLocation()
{
	if (bb_successCallback && bb_errorCallback)
	{
		if(blackberry.location.latitude==0 && blackberry.location.longitude==0)
		{
			//http://dev.w3.org/geo/api/spec-source.html#position_unavailable_error
			//POSITION_UNAVAILABLE (numeric value 2)
			bb_errorCallback({message:"Position unavailable", code:2});
		}
		else
		{
			var timestamp=null;
			//only available with 4.6 and later
			//http://na.blackberry.com/eng/deliverables/8861/blackberry_location_568404_11.jsp
			if (blackberry.location.timestamp)
			{
				timestamp=new Date(blackberry.location.timestamp);
			}
			bb_successCallback({timestamp:timestamp, coords: {latitude:blackberry.location.latitude,longitude:blackberry.location.longitude}});
		}
		//since blackberry.location.removeLocationUpdate();
		//is not working as described http://na.blackberry.com/eng/deliverables/8861/blackberry_location_removeLocationUpdate_568409_11.jsp
		//the callback are set to null to indicate that the job is done
		
		bb_successCallback = null;
		bb_errorCallback = null;		
	}
		 
}

var geo_position_js=function() {



	var pub = {};		
	var provider=null;

	
	pub.getCurrentPosition = function(successCallback,errorCallback,options)
	{
		
		provider.getCurrentPosition(successCallback, errorCallback,options);	
		
	}

	pub.init = function()
	{
		
		try
		{
			if (typeof(geo_position_js_simulator)!="undefined")
			{
				provider=geo_position_js_simulator;
			}		
			else if (typeof(bondi)!="undefined" && typeof(bondi.geolocation)!="undefined")
			{
				provider=bondi.geolocation;
			}
			else if (typeof(navigator.geolocation)!="undefined") 
			{
				provider=navigator.geolocation;
				pub.getCurrentPosition = function(successCallback, errorCallback, options)
				{
				
					function _successCallback(p)
					{
						
						//for mozilla geode,it returns the coordinates slightly differently
						if(typeof(p.latitude)!="undefined")
						{						
							successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude,longitude:p.longitude}});

						}
						else
						{
							successCallback(p);
						}
						
					}
					provider.getCurrentPosition(_successCallback,errorCallback,options);
				}			
				
				
			}
			else if(typeof(window.google)!="undefined")
			{						
				provider=google.gears.factory.create('beta.geolocation');
											
			}	
			else if (typeof(Mojo.Service.Request)!="Mojo.Service.Request")
			{
				provider=true;
				pub.getCurrentPosition = function(successCallback, errorCallback, options)
				{
				  
				parameters={};
				if(options)
				{
					 //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition
					 if (options.enableHighAccuracy && options.enableHighAccuracy==true)
					 {
						parameters.accuracy=1;					
					 }
					 if (options.maximumAge)
					 {
						parameters.maximumAge=options.maximumAge;					
					 }
					 if (options.responseTime)
					 {
						if(options.responseTime<5)
						{
							parameters.responseTime=1;
						}
						else if (options.responseTime<20)
						{
							parameters.responseTime=2;
						}					
						else 
						{
							parameters.timeout=3;
						}						
					 }															
				}
				
				 	
				 r=new Mojo.Service.Request('palm://com.palm.location', {
				 	method:"getCurrentPosition",
				 	    parameters:parameters,
				 	    onSuccess: function(p){successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude, longitude:p.longitude,heading:p.heading}});},
				 	    onFailure: function(e){
								if (e.errorCode==1)
								{
									errorCallback({code:3,message:"Timeout"});
								}
								else if (e.errorCode==2)
								{
									errorCallback({code:2,message:"Position Unavailable"});
								}
								else 
								{
									errorCallback({code:0,message:"Unknown Error: webOS-code"+errorCode});
								}							
							}
				 	    });				
				}
				
			}
			else if (typeof(device)!="undefined" && typeof(device.getServiceObject)!="undefined") 
			{
				provider=device.getServiceObject("Service.Location", "ILocation");
				
				//override default method implementation				
				pub.getCurrentPosition = function(successCallback, errorCallback, options)
				{
					function callback(transId, eventCode, result) {
					    if (eventCode == 4) 
						{
					        errorCallback({message:"Position unavailable", code:2});
					    }
						else
						{
							//no timestamp of location given?
							successCallback({timestamp:null, coords: {latitude:result.ReturnValue.Latitude, longitude:result.ReturnValue.Longitude, altitude:result.ReturnValue.Altitude,heading:result.ReturnValue.Heading}});
					 	}
					}
					//location criteria
				    var criteria = new Object();
    				criteria.LocationInformationClass = "BasicLocationInformation";					
					//make the call
					provider.ILocation.GetLocation(criteria,callback);					
				}
			}									
			else if(typeof(window.blackberry)!="undefined" && blackberry.location.GPSSupported)
			{

				// set to autonomous mode
				blackberry.location.setAidMode(2);
				
				//override default method implementation				
				pub.getCurrentPosition = function(successCallback,errorCallback,options)
				{
					
					//passing over callbacks as parameter didn't work consistently 
					//in the onLocationUpdate method, thats why they have to be set
					//outside
					bb_successCallback=successCallback;
					bb_errorCallback=errorCallback;
					//function needs to be a string according to
					//http://www.tonybunce.com/2008/05/08/Blackberry-Browser-Amp-GPS.aspx
					blackberry.location.onLocationUpdate("handleBlackBerryLocation()");
					blackberry.location.refreshLocation();	

				}
				provider=blackberry.location;
					
			}
		}
		catch (e){ /*console.log(e);*/ }		
		
		
		return  provider!=null;
	}
	

	return pub;
}();
