var EXPORTED_SYMBOLS = ['SearchService'];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://livemargins/webjsm.js");

var Application = Components.classes["@mozilla.org/fuel/application;1"]
                  .getService(Components.interfaces.fuelIApplication);

if (typeof JSON === 'undefined' || JSON == null) { //this is for version lower than 3.5
	Components.utils.import("resource://livemargins/json2.js");
}

// "bind" is not defined in Firefox3
if (!Function.prototype.bind) {
	Function.prototype.bind = function (context) {
		var __method = this, args = Array.prototype.slice.call(arguments, 1);
		return function() {
			return __method.apply(context, args.concat(Array.prototype.slice.call(arguments, 0)));
		}
	};
}

var SearchService = {
	initialized: false,
	webjsm: null,
	geoposition: null,
	topicTimer: null,
	checkInterval: 120 * 60 * 1000,
	hotKeywords: [],
	positionCallbacks: [],

	init: function(){
		if (this.initialized)
			return;

		Application.console.log("[livemargins - SearchService] Init-ing WebJsModule");
		this.webjsm = new WebJsModule();
		this.webjsm.importScript("resource://livemargins/3rd/jquery.js");
		this.webjsm.importScript("resource://livemargins/3rd/jquery_setup.js");
		this.webjsm.importScript("resource://livemargins/3rd/template.js");

		this.loadGeolocationData(500);
		this.setTopicTimer(5 * 1000);

		this.initialized = true;
	},

	getWebJsModule: function() {
		return this.webjsm;
	},

	setTopicTimer: function(timeout){
		if (this.topicTimer === null) {
			this.topicTimer = Components.classes['@mozilla.org/timer;1']
							.createInstance(Components.interfaces.nsITimer);
		} else {
			this.topicTimer.cancel();
		}

		var self = this;
		var timerCallback = {
			notify: function(timer) { self.updateHotKeywords(); }
		};

		this.topicTimer.initWithCallback(timerCallback, timeout, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
	},

	updateHotKeywords: function(){
		// Application.console.log("[MB] Search application starts loading hot keywords ~ ");

		var self = this;
		jQuery = this.getWebJsModule().jQuery;

		jQuery.ajax({
			url:"http://i.g-fox.cn/sina/gethottopic.php",
			method: "GET",
			dataType: "text",
			success: function(txt){
				var data = JSON.parse(txt);
				if (data.count > 0) {
					self.hotKeywords = new Array();
					var totalResult = 0;
					for (var i = 0; i < data.result.length; i += 1) {
						var visibleName = jQuery.trim(data.result[i].title);
						var keywords = jQuery.trim(data.result[i].keyword.replace(/~/g, " "));
						self.hotKeywords.push({
							'name': visibleName,
							'keywords': encodeURIComponent(keywords),
							'total': data.result[i].total,
							'hotness': 'rank'
						});
						totalResult += data.result[i].total;
					}

					var average = totalResult / data.result.length;
					for (var i = 0; i < data.result.length; i += 1) {
						var rank = Math.floor(Math.atan(Math.exp(Math.log(data.result[i].total / average) * 0.25)) * 6 + 1);
						self.hotKeywords[i].hotness += rank;
					}
				}

				self.setTopicTimer(self.checkInterval);
			},
			error: function(request, status){
				Application.console.log(status);
				self.setTopicTimer(self.checkInterval);
			},
		});
	},

	getHotKeywords: function(){
		return this.hotKeywords;
	},

	loadGeolocationData:function(timeout) {
		var self = this;

		function _getGeolocation() {

			var geoClass = Components.classes['@mozilla.org/geolocation;1'];
			if (false) {
				// Yeah, we have the geolocation service;
				var geolocation = geoClass.getService(Components.interfaces.nsIDOMGeoGeolocation);
				geolocation.watchPosition(
					function(position) {
						self.geoposition = {
							latitude: position.coords.latitude,
							longitude: position.coords.longitude,
							country: position.address.country,
							city: position.address.city
						};
						logObject(self.geoposition);
						Application.console.log("[MB] Get geolocation data - " + self.geoposition.city);
						self.positionCallback();
					},
					function(error) {
						self.geoposition = null;
						var status = "Error " + error.code;
						switch (error.code) {
						case Components.interfaces.nsIDOMGeoPositionError.PERMISSION_DENIED:
							status = "permission denied";
							break;
						case Components.interfaces.nsIDOMGeoPositionError.POSITION_UNAVAILABLE:
							status = "position unavailable";
							break;
						case Components.interfaces.nsIDOMGeoPositionError.TIMEOUT:
							status = "timeout";
							break;
						}
						Application.console.log("[MB] Fail to get geolocation data: " + status);
						self.positionCallback();
					}
				);
			} else {
				// We don't have the geolocation service, so to send our
				// request to a wifi geolocation network provider
				// code taken from NetworkGeolocationProvider.js
				var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
				xhr.mozBackgroundRequest = true;
				xhr.open("POST", "https://www.google.com/loc/json", false);
				xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;

				xhr.onerror = function(req) {
					Application.console.log("[MB] geo location error: " + req);
					self.positionCallback();
				};

				xhr.onload = function (req) {
					try {
						var response = JSON.parse(req.target.responseText);
						if ('location' in response) {
							self.geoposition = {
								latitude: response.location.latitude,
								longitude: response.location.longitude,
								country: response.location.address.country,
								city: response.location.address.city
							};
	//						logObject(self.geoposition);
							Application.console.log("[MB] Get geolocation data - " + self.geoposition.city);
							self.positionCallback();
						}
					} catch (e){
						Application.console.log("[MB] geo location error: " + e);
						self.positionCallback();
					}
				};

				var request = {
					version: "1.1.0",
					request_address: true
				};

				var jsonString = JSON.stringify(request);
				if(xhr.readyState == 1)
					xhr.send(jsonString);
			}
		}

		var timer = Components.classes['@mozilla.org/timer;1']
						.createInstance(Components.interfaces.nsITimer);
		var timerCallback = {
			notify: function(timer) { _getGeolocation(); }
		};

		timer.initWithCallback(timerCallback, timeout, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
	},
	getGeoPosition: function() {
		return this.geoposition;
	},
	asyncGetGeoPosition: function(callback) {
		if (this.initialized) {
			callback(this.geoposition);
		} else {
			this.positionCallbacks.push(callback);
			this.init();
		}
	},
	positionCallback: function() {
		for (var i = 0, l = this.positionCallbacks.length; i < l; i++) {
			(this.positionCallbacks[i])(this.geoposition);
		}
	}
};

function logObject(obj) {
	var x = [];
	for (var key in obj) {
		if (typeof obj[key] === 'function') {
			x.push(key + ": function");
		} else {
			x.push([key, obj[key]].join(' = '));
		}
	}
	Application.console.log(x.join('\r\n'));
}
