// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2009
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL

/**************************************************************************
 * Imports
 **************************************************************************/
Components.utils.import("resource:///modules/FlockDateFormatter.jsm");

const PREF_DIGG_HIGHLIGHT_THRESHOLD = "flock.service.digg.highlightThreshold";
const MIN_THRESHOLD = 1000;
const TOP_STORIES_REFRESHED_STR = "topStoriesRefreshed";

var diggPopup = {
  mInitialized: false,
  mDiggPopup: null,
  mLogger: null,
  mDiggService: null, 
  mSb: null,
  mMetrics: null,
  mObs: null,

  POPULAR_THRESHOLD: 5000,

  _init: function diggPopup__init() {
    this.mDiggPopup = document.getElementById("diggPopup");
    if (!this.mDiggPopup) {
      return;
    }
    getBrowser().addProgressListener(this, CI.nsIWebProgress.NOTIFY_LOCATION);
    this.mLogger = CC["@flock.com/logger;1"].createInstance(CI.flockILogger);
    this.mLogger.init("diggPopup");
    this.mMetrics = CC["@flock.com/metrics-service;1"]
                    .getService(CI.flockIMetricsService);
    this.mLogger.debug("._init()");
    this.mPrefBranch = CC["@mozilla.org/preferences-service;1"]
                       .getService(CI.nsIPrefBranch2);
    this.mPrefBranch.addObserver(PREF_DIGG_HIGHLIGHT_THRESHOLD, this, false);
    this.mSb = CC["@mozilla.org/intl/stringbundle;1"]
               .getService(CI.nsIStringBundleService)
               .createBundle("chrome://flock/locale/people/people.properties");
    this.mIOService = CC["@mozilla.org/network/io-service;1"]
                      .getService(CI.nsIIOService);
    this.mGlobalHistory = CC["@mozilla.org/browser/global-history;2"]
                          .getService(CI.nsIGlobalHistory2);
    this.mObs = CC["@mozilla.org/observer-service;1"]
                .getService(CI.nsIObserverService);
    this.mObs.addObserver(this, TOP_STORIES_REFRESHED_STR, false);

    var inst = this;
    this.mInitialized = true;
    // We need to explicitly call getTopStories to initiate getting regular
    // updates.
    this.getTopStories();
  },

  _uninit: function diggPopup__uninit() {
    if (this.mInitialized) {
      this.mLogger.debug("._uninit()");
      this.mPrefBranch.removeObserver(PREF_DIGG_HIGHLIGHT_THRESHOLD, this,
                                      false);
      this.mObs.removeObserver(this, TOP_STORIES_REFRESHED_STR);
      this.mInitialized = false;
    }
  },

  getDiggButton: function diggPopup_getDiggButton() {
    return document.getElementById("digg-button");
  },

  getHighlightThreshold: function diggPopup_getHighlightThreshold() {
    var threshold = this.mPrefBranch
                        .getIntPref(PREF_DIGG_HIGHLIGHT_THRESHOLD);
    if (threshold < MIN_THRESHOLD) {
      return MIN_THRESHOLD;
    } else {
      return threshold;
    }
  },

  observe: function diggPopup_observe(aSubject, aTopic, aData) {
    this.mLogger.debug("observe()");
    if (aTopic == TOP_STORIES_REFRESHED_STR ||
        (aTopic == "nsPref:changed" && aData == PREF_DIGG_HIGHLIGHT_THRESHOLD))
    {
      this.getTopStories();
    }
  },

  _diggService: function diggPopup__diggService() {
    if (!this.mDiggService) {
      this.mDiggService = CC["@flock.com/webservice/digg;1"]
                          .getService(CI.flockIWebService);
    }
    return this.mDiggService;
  },

  getTopStories: function diggPopup_getTopStories() {
    var diggBtn = this.getDiggButton();
    if (!diggBtn || diggBtn.hasAttribute("hidden")) {
      return;
    }
    var inst = this;
    var observeListener = {
      QueryInterface: function obs_queryInterface(aIID) {
        if (aIID.equals(CI.nsISupports) ||
            aIID.equals(CI.flockIListener))
        {
          return this;
        }
        throw Components.results.NS_ERROR_NO_INTERFACE;
      },
      onSuccess: function obs_onSuccess(aSubject, aTopic) {
        var wm = CC["@mozilla.org/appshell/window-mediator;1"]
                 .getService(CI.nsIWindowMediator);
        var win = wm.getMostRecentWindow("navigator:browser");
        var url = win.document.getElementById("content").currentURI.spec;
        inst.enableDiggMan();
        inst.updateDiggMan(url, aSubject);
      },
      onError: function obs_onError(aError, aTopic) {
        inst.disableDiggMan();
      }
    };
    // Bug 13212, 13288: load only top stories
    inst.mLogger.debug("Updating diggPopup with latest top stories");
    inst._diggService().getTopStories(observeListener);
  },

  QueryInterface: function diggPopup_QueryInterface(aIID) {
    if (aIID.equals(CC.nsIWebProgressListener) ||
        aIID.equals(CI.nsISupports))
    {
      return this;
    }
    throw Components.results.NS_NOINTERFACE;
  },

  /**
   * void onLocationChange(in nsIWebProgress aProgress,
   *                       in nsIRequest aRequest,
   *                       in nsIURI aURI);
   * @see nsIWebProgressListener#onLocationChange
   */
  onLocationChange: function diggPopup_locationChange(aProgress,
                                                      aRequest,
                                                      aURI)
  {
    var diggBtn = this.getDiggButton();
    if (diggBtn && !diggBtn.hasAttribute("hidden")) {
      var url = aURI.spec;
      // Disable the Digg This Story button for non-http pages and pages in
      // digg.com domain.
      if (!(url.match(/^https?:\/\//)) || url.match(/^https?:\/\/digg\.com/)) {
        document.getElementById("diggIt").setAttribute("disabled", "true");
      } else {
        document.getElementById("diggIt").removeAttribute("disabled");
      }
    }
  },

  /** @see nsIWebProgressListener#onProgressChange */
  onProgressChange: function diggPopup_progressChange(aProgress,
                                                      aRequest,
                                                      aCurSelfProgress,
                                                      aMaxSelfProgress,
                                                      aCurTotalProgress,
                                                      aMaxTotalProgress)
  {
  },

  /** @see nsIWebProgressListener#onSecurityChange */
  onSecurityChange: function diggPopup_securityChange(aProgress,
                                                      aRequest,
                                                      aState)
  {
  },

  /** @see nsIWebProgressListener#onStateChange */
  onStateChange: function diggPopup_stateChange(aProgress,
                                                aRequest,
                                                aFlag,
                                                aStatus)
  {
  },

  /** @see nsIWebProgressListener#onStatusChange */
  onStatusChange: function diggPopup_statusChange(aProgress,
                                                  aRequest,
                                                  aStatus,
                                                  aMessage)
  {
  },

  show: function diggPopup_show() {
    if (this.mIsOpen) {
      return;
    }
    if (!document.getElementById("digg-button") ||
        document.getElementById("digg-button").hasAttribute("disabled"))
    {
      return;
    }
    this.mDiggPopup.showPopup(this.getDiggButton(),
                              -1,
                              -1,
                              "popup",
                              "bottomleft",
                              "topleft");
    this.mMetrics.report("DiggManFlyout-Click", null);
  },

  hide: function diggPopup_hide() {
    this.mDiggPopup.hidePopup();
  },

  updateDiggMan: function diggPopup_updateDiggMan(aUrl, aResult) {
    this.mLogger.debug("updateDiggMan()");
    if (!document.getElementById("digg-button")) {
      return;
    }

    // Bug 13212: this function should refresh both top stories and # of
    // diggs for the current page, but now it's only top stories. If you need
    // to reactivate page info, look in SVN for the code that used to be
    // here (around revision 18556)

    // Disable the Digg This Story button for non-http pages and pages in
    // digg.com domain.
    if (!(aUrl.match(/^https?:\/\//)) || aUrl.match(/^https?:\/\/digg\.com/)) {
      document.getElementById("diggIt").setAttribute("disabled", "true");
    } else {
      document.getElementById("diggIt").removeAttribute("disabled");
    }

    aResult.QueryInterface(CI.nsIPropertyBag);
    var topStories = aResult.getProperty("topStories");
    if (topStories) {
      var nsJSON = CC["@mozilla.org/dom/json;1"].createInstance(CI.nsIJSON);
      this.loadTopStories(nsJSON.decode(topStories));
    }
  },

  loadTopStories: function diggPopup_loadTopStories(aStories) {
    this.mLogger.debug(".loadTopStories()");
    if (!document.getElementById("digg-button")) {
      return;
    }
    this.removeTopStories();
    var topStoriesContainer = document.getElementById("topStoryContent");
    for (var k = 0; k < aStories.length; k++) {
      var story = aStories[k];
      var label = document.createElement("label");
      var id = "topStory_" + story.id;
      label.setAttribute("value", story.title + " (" + story.diggs + " diggs)");
      label.setAttribute("id", id);
      // Digg url with Flock tracking code
      label.setAttribute("src", story.link);
      // Digg url without Flock tracking code
      label.setAttribute("origLink", story.origLink);
      // Actual story url
      label.setAttribute("url", story.url);
      label.setAttribute("diggs", story.diggs);
      label.setAttribute("onclick", "diggPopup.performAction('" + id + "');");     
      label.setAttribute("class", "storyLink");

      topStoriesContainer.appendChild(label);
    }

    this.highlightTopStories();
  },

  highlightTopStories: function diggPopup_highlightTopStories() {
    var topStoriesContainer = document.getElementById("topStoryContent");
    // Start at i = 1 since we don't need to highlight the label
    for (var i = 1; i < topStoriesContainer.childNodes.length; i++) {
      var story = topStoriesContainer.childNodes[i];
      var linkURI = this.mIOService.newURI(story.getAttribute("src"), null, null);
      var origLinkURI = this.mIOService.newURI(story.getAttribute("origLink"), null, null);
      var realURI = this.mIOService.newURI(story.getAttribute("url"), null, null);
      var diggs = story.getAttribute("diggs");

      // Only highlight the story as popular if both:
      //   (1) story digg count >= threshold pref value
      //   (2) story has *not* been visited before
      // A Digg story is considered "visited" if any of the 3 above URLs
      // have been visited.
      if (diggs >= this.getHighlightThreshold() &&
          !this.mGlobalHistory.isVisited(linkURI) &&
          !this.mGlobalHistory.isVisited(origLinkURI) &&
          !this.mGlobalHistory.isVisited(realURI))
      {
        story.setAttribute("class", "storyLink popularStory");
      } else {
        story.setAttribute("class", "storyLink");
      }
    }

    this.updateState();
  },

  removeTopStories: function diggPopup_removeTopStories() {
   var topStoriesContainer = document.getElementById("topStoryContent");
   while (topStoriesContainer.childNodes.length > 1) {
     topStoriesContainer.removeChild(topStoriesContainer.lastChild);
   }
  },

  disableDiggMan: function diggPopup_disableDiggMan() {
    if (document && document.getElementById("digg-button")) {
      document.getElementById("digg-button").removeAttribute("on");
      document.getElementById("digg-button").setAttribute("disabled", "true");
    }
  },
  
  enableDiggMan: function diggPopup_enableDiggMan() {
    if (document && document.getElementById("digg-button")) {
      document.getElementById("digg-button").removeAttribute("disabled");
    }
  },

  loadMediaBar: function diggPopup_loadMediaBar(aShortName, aQuery, aName)
  {
    var win = _wm.getMostRecentWindow("navigator:browser");
    if (win) {
      win.FlockTopbar.selectById("flock_MediabarTopbarBroadcaster", true);
      win.mediabar.loadQuery(aShortName, aQuery, aName);
    }
    diggPopup.hide();
  },

  diggIt: function diggPopup_diggIt() {
    var wm = CC["@mozilla.org/appshell/window-mediator;1"]
             .getService(CI.nsIWindowMediator);
    var win = wm.getMostRecentWindow("navigator:browser");
    if (!win) {
      return; 
    }
    var url = win.gBrowser.currentURI.spec;

    var inst = this; 
    var urlInfo_Listener = {
      onSuccess: function loc_success(aResult) {
        aResult.QueryInterface(CI.nsIPropertyBag);
        url = aResult.getProperty("diggUrl");
        document.getElementById("diggIt").src = url;
        inst.performAction("diggIt");
      },      
      onError: function loc_error(aError) {
        inst.mLogger.error("getDiggInfo_onError(..., '" + aError + ", ...)");
      }
    }
    this._diggService().loadDiggInfo(url, urlInfo_Listener, false); 
  },

  updateState: function diggPopup_updateState() {
    var topStoriesContainer = document.getElementById("topStoryContent");
    var storyClass;
    // i = 0 is the label
    for (var i = 1; i < topStoriesContainer.childNodes.length; i++) {
      storyClass = topStoriesContainer.childNodes[i].getAttribute("class");
      if (storyClass.indexOf("popularStory") != -1) {
        document.getElementById("digg-button").setAttribute("on", "true");
        return;
      }
    }

    document.getElementById("digg-button").removeAttribute("on");
  },

  performAction: function diggPopup_performAction(aId) {
    var story = document.getElementById(aId);
    var url = story.src ? story.src : story.getAttribute("src");

    var windowManager = CC["@mozilla.org/appshell/window-mediator;1"]
                        .getService(CI.nsIWindowMediator);
    var win = windowManager.getMostRecentWindow("navigator:browser");
    if (win && url) {
      win.openUILinkIn(url, "tab");
      // Unhighlight the clicked story
      story.setAttribute("class", "storyLink");
      this.updateState();
    }
    diggPopup.hide();
    this.recordMetric(aId);
  },

  recordMetric: function diggPopup_recordMetric(aId) {
    switch (aId) {
      case "diggIt":
        this.mMetrics.report("DiggManFlyout-DiggIt-Click", "submit");
        break;

      default:
        if (aId.indexOf("topStory_") > -1) {
          this.mMetrics.report("DiggManFlyout-TopFive-Click", null);
        }
        break;
    }
  }
};

function flock_DiggPopupInit() {
  diggPopup._init();
}

function flock_DiggPopupUninit() {
  diggPopup._uninit();
}

window.addEventListener("load", flock_DiggPopupInit, false);
window.addEventListener("unload", flock_DiggPopupUninit, false);
