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 = Cc["@mozilla.org/fuel/application;1"]
                    .getService(Ci.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,
  checkInterval: 120 * 60 * 1000,
  hotKeywords: [],
  positionCallbacks: [],

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

    Application.console.log("[livemargins - SearchService] Init-ing WebJsModule");
    this.loadGeolocationData(500);
    this.initialized = true;
  },

  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'));
}

