/* poller.js
 * Polling for state changes.
 * ------------------------------------------------------------------------ */

var poller = {


  listeners_ : [],
  api_ : null,
  deck_ : null,
  searchmode_ : 1,
  busy_: 0,

  /* js interval timer handle */
  handle_ : null,
  listhandle_ : null,
  geohandle_ : null,
  
  /* Max geo prevents geodata calls beyond x number of times. 
     Geodata call will never end if no tweets are found for a list. */
  maxgeocall : 5,

  /* Model state from the server. */
  s_tweetcount : null,
  s_global_tweet_count : null,
  s_usercount : null,
  s_twitterup : null,
  s_ssdup : null,
  s_ssdupt : null,
  s_googup : false,
  s_backfilling: null,



  /* Some code depends on the fact that poller only uses two props
     from deck:  get_newest_tweet and get_location. */
  init : function(api, deck, onsearch) {
    poller.api_ = api;
    poller.deck_ = deck;
    poller.searchmode_ = onsearch;
  },


  poll : function(interval) {
    if (poller.handle_) {
      clearInterval(poller.handle_);
      poller.handle_ = 0;
    }
    poller.do_poll();
    poller.handle_ = setInterval('poller.do_poll()', interval);
  },
  
  // Set interval for polling
  listpoll_timer : function(interval) {
    if(poller.listhandle_) {
      clearInterval(poller.listhandle_);
      poller.listhandle_ = 0;
    }
    poller.poll_list_tweet();
    poller.listhandle_ = setInterval('poller.poll_list_tweet()', interval);
  },
  
  // Set interval for pulling geodata, use for List result ONLY
  geopoll_timer : function(interval) {
    if(poller.geohandle_) {
      clearInterval(poller.geohandle_);
      poller.geohandle_ = 0;
    }
    poller.geohandle_ = setInterval('poller.updategeo()', interval);
  },

  // Fires ajax call to geodata if no circles are on the map
  updategeo : function() {
    var polygons = map.getPane(G_MAP_OVERLAY_LAYER_PANE);
    // When no circles exist on the map, call geodata again.
    if(polygons.children.length == 0) {
      CIRCLES.reload();
      // This will allow only 5 calls to prevent excessive loading on server
      poller.maxgeocall--;
    }
    if(poller.maxgeocall == 0) {
      clearInterval(poller.geohandle_);
    }
  },

  /* Function used for fetching tweets for a list */
  poll_list_tweet : function() {
    if(poller.busy_) {
        return;
    }
    poller.busy_ = 1;
    var urlloc = poller.api_.get_url("list");
    if (urlloc != "") {
        $.ajax({
            type: "GET",
            url: urlloc + "/" + poller.deck_.get_newest_tweet()  
        });
    }
    poller.busy_ = 0;
  },

  /* Listen for events from the poller.  Arg should be an object with
     the following functions on it:


     twitterstateupdate : function(n) { ... }
       - Called with twitter state info true = up, false = down

     ssdstateupdate : function(n) { ... }
       - Called with ssd state info true = up, false = down

     googlestateupdate : function(n) { ... }
       - Called with google state info true = up, false = down

     tweetcountchange : function(n) { ... }
       - Called when tweetcount changes

     usercountchange : function(n) { ... }
       - Called when user count changes

     backfillingstateupdate : function(n) { ... }
       - Called when backfilling state changes.

     searcherror : function(n) { ... }
       - Called when search returns error.  Message is at n[0].
  */
  add_listener : function(cb) {
    poller.listeners_.push(cb);
  },


  get_tweet_count : function() {
    return poller.s_tweetcount;
  },


  get_user_count : function() {
    return poller.s_usercount;
  },


  is_twitter_up : function() {
    return poller.s_twitterup;
  },


  is_ssd_up : function() {
    return poller.s_ssdup;
  },


  is_google_up : function() {
    return poller.s_googup;
  },


  get_ssd_uptime : function() {
    return poller.s_ssdupt;
  },


  /* Private method used to notify all listeners when an event 
     occurs. */
  notify : function(what, args) {
    for(var i=0; i < poller.listeners_.length; ++i) {
      if (poller.listeners_[i][what]) {
        poller.listeners_[i][what](args);
      }
    }
  },


  /* Private function to do the polling.  Called from js interval 
     timer. */
  do_poll : function() {
    if (poller.busy_) {
        return;
    }
    poller.busy_ = 1;
    if (poller.searchmode_) {
      poller.api_.search_status
      (
       poller.deck_.get_newest_tweet(),
       poller.deck_.get_location(),
       poller.deck_.get_date(),
       poller.deck_.get_author(),
       poller.deck_.get_keyword(),
       poller.deck_.startDR_,
       poller.deck_.endDR_,
       function(data) {
         poller.set_tweet_count(data['tweet_count'], data['new_tweets'], data['global_tweet_count'], data['loading']);
         poller.set_user_count(data['user_count']);
         poller.set_ssd_up(data['state']['ssd_up'] == 1);
         poller.set_twitter_up(data['state']['twitter_up'] == 1);
         poller.set_ssd_upsince(data['state']['ssd_up_since']);
         poller.set_google_up(data['state']['google_up'] == 1);
         poller.set_backfilling_status(data['backfilling'] == 1);
         if (data['iserror'] == 1) {
           poller.set_error(data['error']);
         }         
         poller.busy_ = 0;
       });
    }
    else {
      /* Just regular poll mode -- no search */
      poller.api_.poll_status
      (
       function(data) {
         poller.set_ssd_up(data['ssd_up'] == 1);
         poller.set_twitter_up(data['twitter_up'] == 1);
         poller.set_ssd_upsince(data['ssd_up_since']);         
         poller.set_google_up(data['google_up'] == 1);
         poller.busy_ = 0;
       });
    }
  },

  set_error : function(msg) {
    poller.notify('searcherror', [msg]);
    // Assume all errors are final.  We can quit polling.
    if (poller.handle_) {
      clearInterval(poller.handle_);
      poller.handle_ = 0;
    }
  },

  set_tweet_count : function(n, m, g, l) {
    poller.s_tweetcount = n;
    poller.s_new_tweets = m;
    poller.s_global_tweet_count = g;
    poller.s_loading = l;
    poller.notify('tweetcountchange', [n, m, g, l]);
  },


  set_user_count : function(n) {
    if (n != poller.s_usercount) {
      poller.s_usercount = n;
      poller.notify('usercountchange', n);
    }
  },


  set_twitter_up : function(n) {
    if (n != poller.s_twitterup) {
      poller.s_twitterup = n;
      poller.notify('twitterstateupdate', n);
    }
  },


  set_google_up : function(n) {
    if (n != poller.s_googup) {
      poller.s_googup = n;
      poller.notify('googlestateupdate', n);
    }
  },


  set_ssd_up : function(n) {
    if (n != poller.s_ssdup) {
      poller.s_ssdup = n;
      poller.notify('ssdstateupdate', n);
    }
  },


  set_ssd_upsince : function(n) { 
    s_ssdupt = n;
  },


  set_backfilling_status : function(n) {
    if (n != poller.s_backfilling) {
      poller.s_backfilling = n;
      poller.notify('backfillingstateupdate', n);
    }
  }


};
